本文介绍了Java泛型投射奇怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用java 8.

I am using java 8.

我最近遇到过这个问题:

I recently came across this:

public class Test {
    public static void main(String[] args) {
        String ss = "" + (Test.<Integer>abc(2));
        System.out.println(Test.<Integer>abc(2));
    }
    public static <T> T abc(T a) {
        String s = "adsa";
        return (T) s;
    }
}

这不会抛出java.lang.ClassCastException。这是为什么?

This does not throw a java.lang.ClassCastException. Why is that?

我一直认为 + System.out.println 调用 toString 。但是当我尝试这样做时,它会按预期抛出异常。

I always thought + and System.out.println calls toString. But when I try to do that it throws an Exception as expected.

String sss = (Test.<Integer>abc(2)).toString();


推荐答案

它不会抛出 ClassCastException 因为从编译的代码中剥离了所有泛型类型信息(一个名为)。基本上,任何类型参数都被 Object 替换。这就是第一个版本有效的原因。这也是代码编译的原因。如果您要求编译器使用 -Xlint:unchecked 标志警告未经检查或不安全的操作,您将收到有关 return 的声明abc()

It doesn't throw a ClassCastException because all generic type information is stripped from the compiled code (a process called type erasure). Basically, any type parameter is replaced by Object. That's why the first version works. It's also why the code compiles at all. If you ask the compiler to warn about unchecked or unsafe operations with the -Xlint:unchecked flag, you'll get a warning about an unchecked cast in the return statement of abc().

使用此声明:

String sss = (Test.<Integer>abc(2)).toString();

这个故事有点不同。虽然类型参数 T Object 替换,但调用代码被转换为显式转换结果的字节代码整数。就好像代码是用带有签名 static Object abc(Object)的方法编写的,并且语句写成:

the story is a bit different. While the type parameter T is replaced by Object, the calling code gets translated into byte code that explicitly casts the result to Integer. It is as if the code were written with a method with signature static Object abc(Object) and the statement were written:

String sss = ((Integer) Test.abc(Integer.valueOf(2))).toString();

也就是说,不仅中的演员表abc()由于类型擦除而消失,编译器在调用代码中插入一个新的强制转换。此转换在运行时生成 ClassCastException ,因为从 abc()返回的对象是字符串,而不是整数

That is, not only does the cast inside abc() go away due to type erasure, a new cast is inserted by the compiler in the calling code. This cast generates a ClassCastException at run time because the object returned from abc() is a String, not an Integer.

注意语句

String ss = "" + (Test.<Integer>abc(2));

不需要强制转换,因为编译器只是提供返回的对象abc()进入对象的字符串连接操作。 (有关如何完成此操作的详细信息因Java编译器而异,但它是对 StringBuilder append方法的调用,或者从Java 9开始,调用方法由 StringConcatFactory 创建。)这里的细节无关紧要;重点是编译器足够聪明,可以识别不需要强制转换。

doesn't require a cast because the compiler simply feeds the object returned by abc() into a string concatenation operation for objects. (The details of how this is done varies with the Java compiler, but it is either a call to a StringBuilder append method or, as of Java 9, a call to a method created by StringConcatFactory.) The details here don't matter; the point is that the compiler is smart enough to recognize that no cast is needed.

这篇关于Java泛型投射奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 19:16