凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 47085
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

2008年8月20日

前回はまず、ジェネリクス型パラメータを伴うList同士の代入互換性について述べました。

今回はそれらのListのadd()メソッドとget()メソッドについて見てきたいと思います。

なお、前回同様に C extends B, B extends A という継承関係があることとして以下話を進めます。

入力値の制約

前回で<? extends B>型には <B>も <C>も <? extends C>も代入できると述べました。

List<? extends B> listBEx = new ArrayList<C>();

ということができるわけですね。 さて、このlistBExにadd()をしてみるとしましょう。

listBEx.add(new B());

実は、これがコンパイルエラーになるのです。 List<? extends B>型には B型をadd()できないのです!

というのも、さきほどlistBExはArrayList<C>型で 初期化しましたね。もし、Bをadd()できるとしたら、 ArrayList<C>型に B型がadd()されてしまうことになります。これでは矛盾してしまいますね。

ですから、List<? extends B>では 型の安全性が破壊されないように、add()できるのは List<? extends B>に代入可能な List全てにadd()可能なものだけしかadd()できないように制約が掛けられます。

? extends Bへの代入

<? extends B>の範囲と ArrayList<C>の範囲、 そしてBオブジェクトの位置を確認してみてください。 Bオブジェクトを型安全にadd()することができないのが分かるでしょうか?

では<? extends B>に対して何がadd()できるのでしょうか?

listBEx.add(null);

だけが可能なのです。使えませんね…。

さて、add()メソッドはこのような制約があるわけですが、get()メソッドなどは普通に使えます。 この違いは何なのでしょうか?

これは、メソッドの引数にジェネリクス型パラメータが含まれる場合に発生する制約です。 引数にジェネリクス型が含まれるadd()などではこのような制約が発生し、 引数にジェネリクス型を含まないget()などでは制約は発生しません。

オブジェクトに対しての入力値がジェネリクスの代入互換性に矛盾しないようにするために 存在する制約というわけなのです。

出力値の制約

List<? extends B>からの get()は問題なく行え、B型の変数に受け取ることができます。

B b = listBEx.get(0);

これは、<? extends B>に <B>が代入されていようが <C>が代入されていようが、 get()で取り出されるオブジェクトは「B型を継承した何か」ですから、B型に安全にキャストできるわけです。

ここで、List<? super B>を考えてみましょう。

<? super B>には <B>や <A>を代入することができます。

ということは、get()で取り出されるオブジェクトは、B型よりも上位のオブジェクト型である可能性があるわけです。 このことから、<? super B>とした場合は 全ての型のトップに位置するObject型でしかget()したオブジェクトを受け取ることができません。

Object o = listBSu.get(0);

これは前回の図を見ると分かることでしょう。再掲します。

階層? super B

入力値の制約 再訪

List<? super B>へのadd()はどうでしょうか?

? super Bへの代入

図を見て分かるように、<? super B>に 代入可能な<B>や <A>は、すべてBオブジェクトを 受け入れることができます。

そのため、ジェネリクスが<? super B>であれば B型をadd()することができます。

posted @ 0:08 | Feedback (211)