[英]Java generics, coming from C++ templates
我发现以下代码在Java中引人注目:
ArrayList<String> l1 = new ArrayList<String>();
ArrayList<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass()); // true
System.out.println(l2.getClass().isAssignableFrom(l1.getClass())); // true too
//ArrayList<Integer> l3 = l1; // won't compile though
我不太了解“ isAssignableFrom”的详细信息。 当然,我希望编译器停止l3 = l2,但这似乎与上一行矛盾? (我确定这里有一些细微之处,这就是我所追求的:-)
编译后,所有<Blah>
信息都会被删除。 就字节码而言,它们都是同一类。
在编译过程中,将检查它们的一致性和兼容性。
因此,当它检查l2.getClass().isAssignableFrom(l1.getClass())
,是说is ArrayList assignable from ArrayList?
答案是肯定的。 但是因为在编译期间它仍然具有类型信息,所以不允许这样做。
这是由Java的泛型实现(而不是草率)造成的,即Type Erasure 。
基本上,编译器会擦除类型信息(例如: ArrayList<String>
和ArrayList<Integer>
都变为ArrayList
),并在必要时添加强制类型转换。 在运行时, l1
和l2
之间没有类型区别,但是编译器不允许您执行赋值-因为它知道类型是不同的。
这是因为删除泛型。
isAssignableFrom()正在测试这些类是否相同,或者第二个类是否是第一个的超类或超接口。
正如其他答案所述,泛型在编译时被删除,因此它们对该方法的输出没有影响。 只有基类才重要。
您想要的内容可能已经由getType()
方法提供,并且l1.getType()
应该返回ArrayList<String>
,而l2.getType()
应该返回ArrayList<Integer>
。
不幸的是,Java在Object上没有getType()
。 在两种情况下, getClass()
返回ArrayList
。
由于您发现l1.getClass() == l2.getClass()
为真,因此l2.getClass().isAssignableFrom(l1.getClass())
应该很明显( x.isAssignableFrom(x)
始终为true,没有?)。 您真正的问题是为什么l1.getClass() == l2.getClass()
为true,这是由于擦除所致。 在运行时只有一个类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.