Java泛型方法类型转换

Java泛型方法类型转换,java,generics,Java,Generics,为什么会这样?代码中的一行运行良好,而另一行类似的代码运行不正常。自动类型转换是否仅在特定条件下发生?我尝试将gt.echoV()分配给一个对象,效果很好;但是当我把它分配给一个字符串时,同样的错误会再次出现 public class GeneMethodTest { public static void main(String... args) { GeneMethodTest gt = new GeneMethodTest(); gt.<Str

为什么会这样?代码中的一行运行良好,而另一行类似的代码运行不正常。自动类型转换是否仅在特定条件下发生?我尝试将gt.echoV()分配给一个对象,效果很好;但是当我把它分配给一个字符串时,同样的错误会再次出现

public class GeneMethodTest {

    public static void main(String... args) {
        GeneMethodTest gt = new GeneMethodTest();
        gt.<String>echoV(); //this line works well
        gt.<String>echoV().getClass();//this line leads to a type cast exception                                                          
    }

    public <T> T echoV() {
        T t=(T)(new Object());                                                                    
        return t;
    }
}
公共类genethodtest{
公共静态void main(字符串…参数){
GeneMethodTest gt=新的GeneMethodTest();
gt.echoV();//这行代码运行良好
gt.echoV().getClass();//此行导致类型转换异常
}
公共电视台{
T=(T)(新对象());
返回t;
}
}

这是完美的,没有什么特别的,泛型的正常使用

gt.<String>echoV(); //this line works well
gt.echoV()//这条线很好用
这里有一些不太明显的东西。因为泛型方法是在运行时定义的,所以jvm不知道泛型方法在编译时将返回什么类型的类,因此出现了classTypeException

gt.<String>echoV().getClass();//this line leads to a type cast exception   
gt.echoV().getClass()//此行导致类型强制转换异常
您应该首先将它分配给一个变量,因为jvm在编译时确实知道变量的类型

String s = gt.<String>echoV();
s.getClass();
String s=gt.echoV();
s、 getClass();
更改此行:

gt.<String>echoV().getClass();
它将编译
(它将返回:class
java.lang.Object

ClassCastException
的根是该方法返回
t
(属于泛型类型
t
,它是一个对象)并尝试将其向下转换为字符串。您还可以更改代码以返回:

return (T)"some-string";
以删除错误

编译器使用泛型来检查预期的对象类型,因此它可以捕获开发人员在编译时犯的错误(相对于运行时错误)。因此,我认为这种使用泛型的方法无法达到目的。

gt.echoV().getClass()生成以下操作序列的等效项:

// Inside echoV
Object t = new Object();  // Note that this is NOT a String!
Object returnValue = t;
// In main
String stackTemp = (String) returnValue;  // This is the operation that fails
stackTemp.getClass();

泛型“免费”得到的是
(String)
强制转换。没有别的。

这个答案可能会有帮助。
(T)(new Object())
是一个未经检查的强制转换-请务必仔细阅读这是什么及其含义,以及类型擦除。是的,我知道@实际上,由于类型擦除,PaulBellora(T)(new Object())在运行时不会执行任何操作。问题是,当我调用gt..echoV()时,自动类转换不会生效,而当我调用gt.echo.getClass()@PaulBellora时,自动类转换会生效。请进一步解释一下您的评论好吗?从文档中可以看出:“如果类型参数是无界的,则用它们的边界或对象替换泛型类型中的所有类型参数。因此,生成的字节码只包含普通类、接口和方法。”@charles_ma这是因为
本身与强制转换无关-它只是泛型方法的类型参数
gt.echoV()
本身不需要编译器插入强制转换,因此在运行时不会失败。实际上,如果执行
System.out.println(gt.echoV())
则会得到
java.lang.ClassCastException
。同样的问题是,System.out.println需要一个字符串作为参数。如果不是这样,它将调用对象的toString(),但在compileat,jvm不知道object是什么,我认为可能是因为在第一行中,我调用了函数,但没有使用引用,因此编译器没有添加任何类强制转换代码;但在第二行中,我尝试使用调用产生的引用,因此编译器必须在那里插入类转换代码~调用System.out.println(gt.echoV())@System时的情况也是如此。exit@user1394628每个对象都有一个
toString()
method,因此它与编译时发生的事情没有任何关系。@user1394628我相信字符串s=gt.echoV();在运行时是否也会产生类强制转换异常?是否需要编写注释?我写了一些不准确的东西吗?我想问题是关于泛型的使用,而不是“getClass()”本身的方法。@System.exit我想我的答案也涵盖了这一点。事实上,我看到你做了一些修改:)。我想我判断你的答案太早了,但是是的,现在你的答案涵盖了这个问题。没错。似乎编译器会决定何时插入代码,而不是每次都插入代码~@charles_ma-Yep,去掉getClass,编译器认为不需要强制转换。
// Inside echoV
Object t = new Object();  // Note that this is NOT a String!
Object returnValue = t;
// In main
String stackTemp = (String) returnValue;  // This is the operation that fails
stackTemp.getClass();