调用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

我正在学习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 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[]