0

次のコードを検討してください。

MyClass myClass= new MyExtendedClass();
myClass.method();

ここで、MyExtendedClass は MyClass のサブタイプです。2番目の文字列コンパイラのコンパイル状態コンパイラで理解したようにmethod()、 のソースコード内のメソッドの存在を確認しましたMyClass。正しい理屈ですか?今考えます

List<Integer> ints= new ArrayList<Integer>();
ints.add(2);
List<? extends Integer> lst = ints;
lst.get(0);

のソースはどこで見ることができますList<? extends Integer>か? 今考えてみましょう:

new ArrayList<Integer>().getClass().equals(
    new ArrayList<String>().getClass());// return true.

そのため、実行時のクラスではArrayList<Integer>ArrayList<String>は同等ですが、コンパイル状態ではそうではありません。なんで?ArrayList<String>とのソースはどこArrayList<Integer>ですか?

4

3 に答える 3

1

型消去を検索します。まず、http://docs.oracle.com/javase/tutorial/java/generics/erasure.html を参照してください

于 2013-09-25T16:36:35.367 に答える
0

myClass.method();合法であるためには、クラスMyClassまたはインターフェースはmethodメソッドを宣言する必要があります。それは正しいです。

とのgetClass結果が等しい理由は、実行時に、型消去がジェネリック型パラメーターを消去し、両方の場合を残し、もちろん両方が等しいためです。とを区別できるのはコンパイラだけです。JVM はジェネリックについてまったく知らなかったので、ジェネリック以前 (Java 1.5 以前) のアプリケーションと後方互換性を保つために型消去が発生します。ArrayList<Integer>ArrayList<String>ArrayListArrayList<Integer>ArrayList<String>

于 2013-09-25T16:38:24.580 に答える
0

Java は C++ のようには機能しません。C++ では、「テンプレート」によって、その参照型を持つ新しいクラスが完全に生成されます。ただし、Java は、テンプレート化されたインスタンス化ごとに新しいクラスを生成するわけではありません。代わりに、型情報はコンパイルおよび実行時の設定として保持されます。したがって、ArrayList<Integer> と ArrayList<String> は同じ実際のクラスを使用します。

型チェックはコンパイラにあり、単純なクラスの場合、これは簡単です。

class Gem {...}
class Ruby extends Gem {...}
class Diamond extends Gem {...}

Gem a;
Ruby b;
Diamond c;

a = b;   //no problem allowed
b = a;   //type problem, need to cast it!
b = c;   //never allowed!

しかし、パラメータ化されたクラスははるかに複雑です

List<Gem> la;
List<Ruby> lb;
List<Diamond> lc;

la = lb;   //not allowed because type is different even though Ruby extends Gem

List<? extends Gem> ld;

ld = la;  //allowed
ld = lb;  //also allowed
ld = lc;  //also allowed

複数の種類のコレクションを保持するコレクション変数を使用できるようにするには、ワイルドカードが必要です。違いは型パラメーターにあります。いずれの場合も、オブジェクト クラス (およびソース コード) は変わりません。

于 2013-09-25T16:41:25.217 に答える