ジェネリッククラスを作る
Object で受けると、取り出すたびにキャストが要る
何か 1 つ値を持っておくクラスを、型を決めずに書くとフィールドは Object になります。
Java
public class Memo {
private Object body;
public Object read() {
return body;
}
}入れるほうは何でも通りますが、取り出すほうが困ります。String text = memo.read(); は通らないので (String) memo.read() とキャストが要り、間違った型でキャストしてもその場では気づけません。実行して初めて ClassCastException で落ちます。数値のつもりの箱に文字列が入っていても、コンパイラは何も言ってくれません。
型は、使う人に決めてもらう
クラス名の右に <T> を書くと、中身の型は使う人が決める、という宣言になります。
Java
public class Memo<T> {
private T body;
public Memo(T body) {
this.body = body;
}
public T read() {
return body;
}
}T は、あとで型が入る場所を押さえておくための札です。実体が決まるのは new するときです。
Java
Memo<String> note = new Memo<>("牛乳を買う");
String text = note.read(); // キャストは要らない
Memo<Integer> count = new Memo<>(3);
int n = count.read();Memo<String> に数値を渡そうとすれば、実行する前にコンパイラが止めてくれます。new Memo<>(...) の山かっこが空なのは、左側に書いた型からコンパイラが埋めてくれるからです。
T に書けるもの、書けないもの
型パラメータの名前には 1 文字の大文字を使う慣習があり、意味ごとにだいたい決まっています。汎用の型なら T、コレクションの要素なら E、キーと値のペアなら K と V です。文法上は好きな名前を付けられますが、慣習から外れるとクラス名と見分けが付かなくなります。
書けない型もあります。Memo<int> とは書けないので、Memo<Integer> のようにラッパー型を使います。また Memo memo = new Memo("x"); と山かっこを省く書き方も文法としては残っていますが、中身が Object 扱いに戻ってしまうので使いません。
課題では、値を 1 つ包んで取り出せるジェネリッククラスを自分で定義し、Solution の中から使います。1 つのファイルにクラスを 2 つ書くか、static を付けた入れ子のクラスにするかのどちらかです。取り出した値を、指定された形の文字列に組み立てて返してください。
要件
Solutionクラスの中 (もしくは同ファイル) に、型パラメータ<T>を持つBox相当のジェネリッククラスを定義することBoxクラスは値を保存するフィールドと、それを取り出すgetValue()相当のメソッドを持つこと (raw 型Boxのままにせず、必ず<>で型を指定すること)boxedValueの内部でBox<String>を生成し、getValue()で取り出した値を使って"Box[" + value + "]"の文字列を返すこと
入出力例
boxedValue("hello") → "Box[hello]"
boxedValue("Java") → "Box[Java]"
boxedValue("") → "Box[]"
boxedValue("こんにちは") → "Box[こんにちは]"