- 締切済み
javaのGenericsが良く分かりません
かなり以前に java プログラミングを少しばかりやっていたので java は少し分かるのですが、最近 また java プログラミング始めてみたのですが、Generics なる機能が「Java SE5.0から導入されたようですが、良く分かりません。 ご存知の方がいらしたら どうか ご教授下さいませm(_ _)m 開発環境 eclipse java 8 class Box<T> { // Object obj; T obj; @SuppressWarnings("unchecked") public T getT(){ return obj; } public void setT(T o){ obj = o; } @SuppressWarnings("unchecked") public void setTExtends(Box<? extends T> o){ obj = (T)o; } } Box<Number> boxN = new Box<Number>( ); Box<Integer> boxI = new Box<Integer>( ); boxN.setT((Number)new Integer(1)); // 当然、正常にコンパイルされる。 boxN.setT(new Integer(1)); // なぜか正常にコンパイルされる。 boxN.setT(boxN.getT()); // 正常にコンパイルされる。 boxN.setT(boxI.getT()); // なぜか正常にコンパイルされる。 boxN.setTExtends((Number)new Integer(1)); // なぜかコンパイル・エラーになる。 boxN.setTExtends(new Integer(1)); // なぜかコンパイル・エラーになる。 boxN.setTExtends(boxN.getT()); // なぜかコンパイル・エラーになる。 boxN.setTExtends(boxI.getT()); // なぜかコンパイル・エラーになる。 boxI.setT(new Integer(1)); // 当然、正常にコンパイルされる。 boxI.setT(boxI.getT()); // 当然、正常にコンパイルされる。 boxI.setTExtends(new Integer(1)); // なぜかコンパイル・エラーになる。 boxI.setTExtends(boxI.getT()); // なぜかコンパイル・エラーになる。
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- wormhole
- ベストアンサー率28% (1626/5665)
「なぜかコンパイル・エラーになる。」とコメントに書かれてる箇所は、あなたがそう思われてるだけで極当然にエラーになるものです。 BoxクラスのsetTExtends(Box<? extends T> o)メソッドの引数の型は、Box<? extends T>なのですから(Boxクラスの変数としてBox<Number>で宣言したときにはTがNumberに置き換わりBox<? extends Number>になりますし、Box<Integer>で宣言したときにはBox<? extends Integer>になります)、 そこに派生関係のないNumberクラスやIntegerクラスのインスタンスを渡してもコンパイラはコンパイルしようがありません。 >boxN.setT(new Integer(1)); // なぜか正常にコンパイルされる。 >boxN.setT(boxI.getT()); // なぜか正常にコンパイルされる。 boxNの型はBox<Number>ですから、setTメソッドの引数の型はNumberです。 new Integer(1)の型はIntegerで、IntegerはNumberの派生クラスです。 boxlの型はBox<Integer>ですから、getTメソッドの戻り値の型はIntegerです。 どこかコンパイルエラーになる要素ありますか?
お礼
返信ありがとう御座います。 > そこに派生関係のないNumberクラスやIntegerクラスのインスタンスを渡してもコンパイラはコンパイルしようがありません。 その辺からして良く理解できていなかったと言うことです。 > boxNの型はBox<Number>ですから、setTメソッドの引数の型はNumberです。 > new Integer(1)の型はIntegerで、IntegerはNumberの派生クラスです。 > boxlの型はBox<Integer>ですから、getTメソッドの戻り値の型はIntegerです。 > どこかコンパイルエラーになる要素ありますか? Generics を使う場合(かつワイルドカードを使わない場合)は同一の型でなければならない、と言う記述から、通常のオブジェクト型も制限されるのかと勘違いしておりました。 こちらでも、イロイロやってみて、分かりました。 (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はElement(要素)対する宣言と言う感じでしょうか。 つまり、この変の区別が全く分かってなかったと言う事です。
補足
訂正 > (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はElement(要素)対する宣言と言う感じでしょうか。 (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はContainer(容器)に対する宣言と言う感じでしょうか。