Java泛型方法类型转换

6

为什么会出现这种情况?一行代码能正常工作,而另一行类似的代码却不能。自动类型转换只在某些条件下发生吗?我尝试将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;
    }
}

1
这个答案可能会有所帮助 https://dev59.com/vnA75IYBdhLWcg3wKluM#3437930 - Kevin DiTraglia
(T)(new Object()) 是一个 未经检查的转换 - 请确保了解它的含义和影响,以及 类型擦除 - Paul Bellora
是的,我知道。@PaulBellora 实际上(T)(new Object())在运行时不会有任何作用,因为类型擦除。问题是当我调用gt.<String>.echoV()时,自动类转换不起作用,而当我调用gt.<Stirng>echo.getClass()时它确实起作用。 - charles_ma
@charles_ma 这是因为 <String> 本身与强制转换无关 - 它只是泛型方法的类型参数。gt.<String>echoV() 单独不需要编译器插入任何强制转换,因此在运行时不会失败。 - Paul Bellora
@alfasin,我不确定我理解你的评论。我建议原帖作者(和其他人)阅读类型擦除和未经检查的转换的概念。 - Paul Bellora
显示剩余5条评论
3个回答

4

gt.<String>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) 的强制转换,没有别的东西。

没错。看起来编译器会自动判断何时插入代码,而不是每次都插入~ - charles_ma
@charles_ma - 是的,去掉getClass,编译器就会认为不需要转换。 - Hot Licks

2

这个很完美,没有什么特别的,只是普通的泛型使用。

gt.<String>echoV(); //this line works well

这里我们有一些不太明显的内容。由于通用方法是在运行时定义的,所以jvm无法在编译时知道通用方法将返回什么类型的类,因此导致了classTypeException异常。

gt.<String>echoV().getClass();//this line leads to a type cast exception   

在编译时,JVM不知道变量的类型,因此您应该先将其分配给一个变量。

String s = gt.<String>echoV();
s.getClass();

2
实际上,如果您执行 System.out.println(gt.<String>echoV()),您会得到一个 java.lang.ClassCastException - Julián Chamalé
相同的问题,System.out.println期望一个字符串作为参数。如果不是这种情况,它将调用对象的toString()方法,但在编译时jvm不知道来自哪个对象。 - Joris W
1
@user1394628 每个对象都有一个toString()方法,因此它与编译时发生的事情无关。 - Nir Alfasi
@user1394628 我相信 String s = gt.<String>echoV(); 也会在运行时产生类转换异常~ - charles_ma
String s = gt.<String>echoV(); 也会失败。 - Hot Licks
显示剩余2条评论

1

更改此行:

gt.<String>echoV().getClass();

到:

(gt.echoV()).getClass();

并且它会编译
(它会返回: class java.lang.Object

ClassCastException的根本原因是方法返回了t(类型为泛型T的对象),而您尝试将其向下转换为字符串。您还可以更改代码以返回:

return (T)"some-string";

为了消除错误。
编译器使用泛型来检查期望的对象类型,这样可以在编译时捕获开发人员所做的错误(与运行时错误相比)。因此,在我看来,使用泛型的方式就失去了其目的。

下投票者,能否写一个评论?我写错了什么吗? - Nir Alfasi
1
我认为问题是关于泛型的使用,而不是´getClass()´方法本身。 - Julián Chamalé
1
@System.exit 我认为我的回答也涵盖了这个问题。 - Nir Alfasi
实际上,我看到你做了一些修改:)。我认为我过早地评判了你的答案,但是现在你的答案确实回答了这个问题。 - Julián Chamalé

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接