Java Casting方法,不知道要转换为什么

The*_*Cup 5 java casting

今天我正在玩Java,我注意到一些奇怪的东西.考虑以下代码:

String foo = cast("hi");
int bar = cast("1");
Run Code Online (Sandbox Code Playgroud)

cast()方法是在这里:

public static <T> T cast(Object value) {
    return (T) value;
}
Run Code Online (Sandbox Code Playgroud)

Java似乎转换"hi"为String,即使我没有传递任何暗示它将是一个String,除了类型.它运行foo良好,但失败了bar,因为你不能将String作为整数.这里发生了什么?

我有两个猜测:

  1. cast方法返回一个Object,并在初始化时自动转换为该类型.

    这没有意义,因为它会给我:

    Type mismatch: cannot convert from Object to int
    
    Run Code Online (Sandbox Code Playgroud)
  2. Java似乎知道它需要转换为String,或者变量的类型.但这是如何工作的?

Ant*_*ond 7

public static <T> T cast(Object value) {
    return (T) value;
}
Run Code Online (Sandbox Code Playgroud)

重要的部分是<T>方法,它意味着该方法将根据方法调用所期望的内容返回一个类型.

String foo = cast("hi"); // left side is a String, <T> will be typed as String
Run Code Online (Sandbox Code Playgroud)


第二个是有点棘手,因为泛型类型不能是原始类型.我猜它会返回最常见的类型Object.

int bar = cast("1"); // left side is primitive
                     // <T> will be typed by with the corresponding non-primitive type.
                     // But it fails because "1" cannot be casted to java.lang.Integer
Run Code Online (Sandbox Code Playgroud)


Tam*_*dus 6

您的强制转换方法执行未经检查的转换,该转换在JVM中专门处理,以保持与非泛型代码的向后兼容性.

在使用泛型的类型系统下,这样的调用不能显示为静态安全.拒绝此类调用将使大量现有代码无效,并阻止它们使用较新版本的库.JLS 5.1.9

调用没有显式类型参数的方法将导致编译器推断调用的类型参数,在这种情况下基于它们的预期返回类型.类型推断,JLS 15.12.2.7..这意味着代码与此等价:

String foo = Caster.<String>cast("hi"); // no exception
int bar = Caster.<Integer>cast("1");    // runtime ClassCastException
Run Code Online (Sandbox Code Playgroud)

原始类型将推断为其盒装版本:

如果A是基本类型,则通过装箱转换将A转换为引用类型U,并且该算法递归地应用于约束U << F.JLS 15.12.2.7.

JVM通过对包含未经检查的强制转换的函数的返回值进行运行时类型检查来确保类型安全,在第一个未删除类型信息的位置(我没有在规范中明确说明它,但事情看起来像这样工作,虽然在Java教程中提到过).在这种情况下,在尝试将值分配给类型化局部变量的情况下,将检查返回值的类型,从而得到a ClassCastException.

为了更好地了解强制执行运行时类型检查转换的时间,下面是一些示例:

Object a3 = Caster.<String>cast(3); // no exception, a3 is now Integer
Object a4 = (String)Caster.<String>cast(3); // an explicit cast causes runtime ClassCastException
Run Code Online (Sandbox Code Playgroud)

编辑:

这是一个关于何时强制执行运行时类型检查的StackOverflow问题:何时是在类型擦除后执行的函数的泛型返回值?