请考虑以下代码:
MyClass myClass= new MyExtendedClass();
myClass.method();
其中MyExtendedClass是MyClass的子类型。正如我在第二个字符串编译器上的编译状态编译器所理解的那样,在源代码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>
的来源在哪里?
答案 0 :(得分:1)
答案 1 :(得分:0)
要使myClass.method();
合法,MyClass
类或接口必须声明method
方法。这是对的。
getClass
结果与ArrayList<Integer>
和ArrayList<String>
相等的原因是,在运行时,类型擦除会删除泛型类型参数,在这两种情况下都会留下ArrayList
,当然,他们都是平等的。只有编译器才能区分ArrayList<Integer>
和ArrayList<String>
。 JVM从未了解泛型,因此类型擦除与预先泛型(Java 1.5之前的版本)应用程序向后兼容。
答案 2 :(得分:0)
Java不像C ++那样工作。在C ++中,“模板”导致完整生成具有该引用类型的新类。但是,Java不会为每个模板化实例化生成新类。相反,类型信息在编译和运行时作为设置进行。所以ArrayList&lt; Integer&gt;和ArrayList&lt; String&gt;使用相同的实际课程。
类型检查在编译器中,对于简单类,这很容易。
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
需要使用通配符来允许您拥有一个包含多种集合的集合变量,其中差异在type参数中。在所有情况下,对象类(和源代码)保持不变。