java - 在 Java 运行时使用泛型 - (T)object - 进行强制转换会发生什么情况?

标签 java class generics compiler-construction casting

据我了解,Java 泛型将泛型方法(或泛型类)中有关参数类型 T 的所有信息都删除了。这就是为什么我们不能使用

新的表达,比如

new T()

instanceof表达式,如

if(obj instanceof T)

在泛型方法中。

我的问题是,当涉及到转换时,参数类型 T 如何在泛型方法中工作。例如,我这里有 3 个简单的类:

public class People {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public People(String name) {
        super();
        this.name = name;
    }

    @Override
    public String toString() {
        return "People [name=" + name + "]";
    }

}

public class GenericClass<T> {

    public T getCast(People p) {
        return (T)p;
    }
}

public class App 
{
    public static void main( String[] args )
    {
        People p = new People("Kewei");

        GenericClass<Integer> genericClass = new GenericClass<Integer>();
        Object p_object = genericClass.getCast(p);

        System.out.println(p_object);
    }
}

当它在通用方法 getCast(People p) 中执行 (T)p 时。它只是将类型 T 作为对象吗?或者它只是在编译时删除了整个 (T) 转换?我读过 Bruce Eckel 的《Thinking in Java》,大致理解为:

Java compiler checks at method's entry/leave points at compile time to make sure the internal consistency of generic method, and inserts casting code (at compile time).

这样理解对吗?

谢谢。

最佳答案

您可以在脑海中想象编译器将带有泛型的代码“重写”为没有泛型的代码。

在通用类中,T 被删除到其上限,在本例中为 Object,但也可以是其他东西。转换为 T 变成转换为 T 的上界(在本例中为 Object,因此它是多余的,编译器可能会跳过它)。该方法类似地返回 T 的上限(即 Object)。因此,没有运行时检查方法内部的转换是否有效。

public class GenericClass {

    public Object getCast(People p) {
        // In this case the cast to T is removed because T's upper bound is Object.
        // But if T's upper bound was, say, Number, then there would still be a cast
        // to the upper bound. e.g. "(Number)p", and the return type would also be Number
        return p;
    }
}

在调用返回 T 的方法的地方,编译器会将强制转换插入到 T 的实际类型中。在这种情况下,在 main 方法中,您有一个 GenericClass<Integer>。 ,所以当getCast返回 T,它被转换为 Integer。所以在这种情况下,运行时检查现在被“移动”到调用方法,而不是带有转换的方法。

// somewhere else
GenericClass genericClass = new GenericClass();
p_object = (Integer)genericClass.getCast(p);

也有可能调用者保留了一个 GenericClass<S>引用(对于其范围内的某些类型参数 S),以便将结果强制转换为 S,而不是特定类型。然后我们将再次重复整个重写过程(即,对 S 的转换被重写为对其上限的转换,调用该方法的地方会将结果转换为它们的实际类型参数)。这意味着运行时检查可能会推迟到另一个地方,依此类推。

关于java - 在 Java 运行时使用泛型 - (T)object - 进行强制转换会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11353555/

相关文章:

java - 如何迭代从对象派生的 ArrayList

java - 这是异常处理滥用吗?

c# - 如何在通用消息接收器中为不同的类类型调用不同的方法?

java - 让类在 java 中工作,构建 Android 应用程序来解析 XML

C# 泛型与 C++ 模板的比较

c# - 如何从开始到特定条件从通用列表中删除项目

java - JBoss 部署错误 : Caused by: java. lang.RuntimeException : . application.xml 中列出的 war 模块在 .ear 中不存在

java - 使用 Apache HTTPClient 时无法释放连接

iPhone:SDK 中应包含的有用类或扩展子类(类别)

Java:没有异常消息错误