Java泛型,来自C++;模板
我发现以下代码在Java中非常出色:Java泛型,来自C++;模板,java,generics,Java,Generics,我发现以下代码在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().
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
ArrayList l1=新的ArrayList();
ArrayList l2=新的ArrayList();
System.out.println(l1.getClass()==l2.getClass());//真的
System.out.println(l2.getClass().isAssignableFrom(l1.getClass());//也是这样
//ArrayList l3=l1;//但不会编译
我不太明白“isAssignableFrom”的细节。当然,我希望编译器停止l3=l2,但它似乎与前一行相矛盾?(我确信这里有一些微妙的地方,这就是我想要的:-)所有的
信息在编译后都会被剥离掉。就字节码而言,它们都是同一个类
在编译过程中,会检查它们的一致性和兼容性
因此,当它检查l2.getClass().isAssignableFrom(l1.getClass())
时,它会说ArrayList可从ArrayList赋值吗?
,答案是肯定的。但是,因为在编译期间它仍然有类型信息,所以它是不允许的。所有的
信息在编译后都会被剥离掉。就字节码而言,它们都是同一个类
在编译过程中,会检查它们的一致性和兼容性
因此,当它检查l2.getClass().isAssignableFrom(l1.getClass())
时,它会说ArrayList可从ArrayList赋值吗?
,答案是肯定的。但是因为在编译过程中它仍然有类型信息,所以它是不允许的。这是由Java的泛型实现(相当草率)造成的,即
基本上,编译器会删除类型信息(例如:ArrayList
和ArrayList
都变成ArrayList
),并在必要时添加强制转换。在运行时,l1
和l2
之间没有类型区别,但编译器不会让您进行赋值-因为它知道类型是不同的。这是由Java的泛型实现(相当草率)造成的,即
基本上,编译器会删除类型信息(例如:ArrayList
和ArrayList
都变成ArrayList
),并在必要时添加强制转换。在运行时,l1
和l2
之间没有类型区别,但编译器不允许您进行赋值-因为它知道类型不同。这是因为泛型。这是因为泛型。isAssignableFrom()正在测试类是否相同,或者如果第二个是第一个的超类或超接口。
正如其他答案所述,泛型在编译时被删除,因此它们对该方法的输出没有影响。只有基类是最重要的
参考:isAssignableFrom()正在测试这些类是否相同,或者第二个类是否是第一个类的超类或超接口。
正如其他答案所述,泛型在编译时被删除,因此它们对该方法的输出没有影响。只有基类是最重要的
引用:您想要的可以由
getType()
方法提供,并且l1.getType()
应该返回ArrayList
,而l2.getType()
应该返回ArrayList
不幸的是,Java在对象上没有
getType()
getClass()
在这两种情况下都返回ArrayList
。您想要的可以通过getType()
方法来实现,并且l1.getType()
应该返回ArrayList
,而l2.getType()
应该返回ArrayList
不幸的是,Java在对象上没有
getType()
getClass()
在这两种情况下都返回ArrayList
。既然你发现l1.getClass()==l2.getClass()
是真的,那么l2.getClass().isAssignableFrom(l1.getClass())
应该是显而易见的(x.isAssignableFrom(x)
应该总是真的,不是吗?)。你真正的问题是为什么l1.getClass()==l2.getClass()
是真的,这是由于擦除。运行时只有一个类。既然您发现l1.getClass()==l2.getClass()
是真的,那么l2.getClass().isAssignableFrom(l1.getClass())
应该是显而易见的(x.isAssignableFrom(x)
应该总是真的,不是吗?)。你真正的问题是为什么l1.getClass()==l2.getClass()
是真的,这是由于擦除。运行时只有一个类。具体来说,这称为类型擦除。关于泛型的Java教程很好地解释了Java泛型的缺陷:是的,感觉有点矛盾,因为有些东西在运行时是真的,但在编译时不是真的,或者,它是可赋值的,但不能赋值。这感觉不太对:-)@Frank我想依赖运行时正确性的心态是糟糕的设计;相反,我们应该设计代码,以便在编译时捕获错误。这并不是说我们总是成功:)当然,我同意这一点。我的主要问题是,阶级是平等的,同时又是不平等的。至于编译时做更多的事情,我喜欢尽可能多地把运行时移到编译时,在C++中(没有机会在java中完成)。在java中,你不能做太多的事情,因为老实说,java能比JIT做得更好。公平地说,它们不是同时相等和不相等,而是在某个时间相等,在另一个时间不相等。具体地说,这称为类型擦除。Java泛型教程非常擅长解释Java泛型的缺陷:是的,感觉有点矛盾,因为有些东西在运行时是正确的,但在编译时不是,或者,它是可赋值的,但是