调用Java泛型方法
我正在学习Java通用特性,不知道如何解释以下调用Java泛型方法,java,generics,type-erasure,generic-method,Java,Generics,Type Erasure,Generic Method,我正在学习Java通用特性,不知道如何解释以下main方法中的第三行: public class Example4 { public static void main(final String[] args) { System.out.println(Util.<String>compare("a", "b")); System.out.println(Util.<String>compare(new String(""), new
main
方法中的第三行:
public class Example4 {
public static void main(final String[] args) {
System.out.println(Util.<String>compare("a", "b"));
System.out.println(Util.<String>compare(new String(""), new Long(1)));
System.out.println(Util.compare(new String(""), new Long(1)));
}
}
class Util {
public static <T> boolean compare(T t1, T t2) {
return t1.equals(t2);
}
}
公共类示例4{
公共静态void main(最终字符串[]args){
System.out.println(Util.compare(“a”、“b”));
System.out.println(Util.compare(新字符串(“”),新长(1));
System.out.println(Util.compare(新字符串(“”),新长(1));
}
}
类Util{
公共静态布尔比较(t1,t2){
返回t1等于(t2);
}
}
第一行编译、运行并返回(按预期)false
第二行没有按预期编译,因为我明确地混合了String
和Long
第三行编译、运行并返回false,但我不确定它是如何工作的:编译器/JVM是否将参数类型T
实例化为对象?(还有,有没有办法获得这种声明类型的T
are runtime?)
谢谢。共享继承的字符串
和长
类型是对象
当您以Util.compare(
的形式运行此函数时,编译器希望找到两个字符串输入,否则会给出一个错误。但是,在没有
的情况下运行此函数会导致使用最接近的共享继承类型—在本例中为对象
因此,当compare
接受t1
和t2
时,它们被转换为对象
,代码运行正常
要在运行时获取实际类型,您需要使用与任何其他对象相同的技术:getClass()
继承自对象
类。是的,对象
是允许它编译的T
的一个选择。从概念上讲,编译器为T
推断一个类型。它特别推断的内容并不重要——只要它能推断某些类型适用于T
,那么它就编译了。推断的类型是什么并不重要,因为它对编译的代码没有影响。答案似乎超出了@Telthien和@newacct的答案。我很想亲自“看看”以下两者之间的区别:
System.out.println(Util.<String>compare("a", "b"));
使用隐式类型
我使用前两行的变体进行了几个实验。这些实验表明,除了使用之外,编译器在编译过程中确实会检查类型,但生成的字节码只引用对象
,即使是在第一行的情况下
下面的代码显示,即使在显式类型参数
的情况下,也可以安全地执行到对象的类型转换
事实上,所有调用都是以Object
作为形式参数类型的方法是有意义的,如前所述。为了避免这种情况,编译器总是使用Object
作为生成的字节码,不管是否有显式类型参数(第一行)或者是一个隐式类型参数,但对象可能有一个与对象不同的公共超类,第二部分(在运行时获取声明的T类型的方法)在Google上搜索“Reified泛型”。请参阅gafter.blogspot.com/2006/11/Reified-Generics-for-java.htmlThe getClass()应用于t1的方法将返回字符串,因为它是运行时类型,不是吗?在做更多研究时,我偶然发现了一个有趣的博客条目:。您也可以使用instanceof
,但速度较慢。但是,从比较中,字符串已匿名化-读取它们的唯一方法是读取类字符串并对其进行解释(至少据我所知)。请注意这一点,即使您链接到它;这种现象称为“类型擦除”.Yeah。基本上,Java将泛型实现为后台类型转换。例如,ArrayList
在内部将每个元素都视为对象,但在使用时会自动将其转换回字符串。
System.out.println(Util.compare(new String(""), new Long(1)));
public final class Example44 {
public static void main(final String[] args) {
System.out.println(new Util44<String>().compare("a", "b"));
System.out.println(new Util44().compare(new String(""), new Long(1)));
}
}
final class Util44<T> {
private T aT;
public boolean compare(T t1, T t2) {
System.out.println(this.aT);
// I was expecting the second and third assignments to fail
// with the first invocation because T is explicitly a String
// and then to work with the second invocation because I use
// a raw type and the compiler must infer a common type for T.
// Actually, all these assignments succeed with both invocation.
this.aT = (T) new String("z");
this.aT = (T) new Long(0);
this.aT = (T) new Object();
return t1.equals(t2);
}
}
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 7, Locals: 1
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 new ca.polymtl.ptidej.generics.java.Util44 [22]
6 dup
7 invokespecial ca.polymtl.ptidej.generics.java.Util44() [24]
10 ldc <String "a"> [25]
12 ldc <String "b"> [27]
14 invokevirtual ca.polymtl.ptidej.generics.java.Util44.compare(java.lang.Object, java.lang.Object) : boolean [29]
17 invokevirtual java.io.PrintStream.println(boolean) : void [33]
20 getstatic java.lang.System.out : java.io.PrintStream [16]
23 new ca.polymtl.ptidej.generics.java.Util44 [22]
26 dup
27 invokespecial ca.polymtl.ptidej.generics.java.Util44() [24]
30 new java.lang.String [39]
33 dup
34 ldc <String ""> [41]
36 invokespecial java.lang.String(java.lang.String) [43]
39 new java.lang.Long [46]
42 dup
43 lconst_1
44 invokespecial java.lang.Long(long) [48]
47 invokevirtual ca.polymtl.ptidej.generics.java.Util44.compare(java.lang.Object, java.lang.Object) : boolean [29]
50 invokevirtual java.io.PrintStream.println(boolean) : void [33]
53 return
Line numbers:
[pc: 0, line: 24]
[pc: 20, line: 25]
[pc: 53, line: 26]
Local variable table:
[pc: 0, pc: 54] local: args index: 0 type: java.lang.String[]