在Java运行时使用泛型 - (T)对象进行转换会发生什么? [英] What happens to casts using generics - (T)object - at run-time in Java?

查看:1404
本文介绍了在Java运行时使用泛型 - (T)对象进行转换会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As far as I understand, Java Generics erases all the information concerning the parameter type T in the generic method (or in the generic class). That's why we can't use

新表达式,例如

new T()

表达式的实例,例如

if(obj instanceof T)

通用方法。

我的问题是当一个通用方法中的参数类型T如何工作。例如,这里有3个简单的类:

My question is how the parameter type T works inside a generic method when it comes to casting. For example, I have 3 simple classes here:

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);
    }
}

当执行 T)p 在通用方法 getCast(People p)中。它只是把类型T作为对象?或者只是在编译时删除整个(T)铸造?我已经阅读了Bruce Eckel的Thinking in Java,我大致理解为:

When it executes the (T)p in the generic method getCast(People p). Does it just take the type T as Object? or It just removes the whole (T) casting at compile time? I've read Bruce Eckel's «Thinking in Java» from which I roughly understand as:


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).

这是否正确?

感谢。

推荐答案

你可以在思想上认为编译器将代码用泛型代码重写为没有泛型的代码。

You can mentally think of the compiler doing a "re-writing" of the code with generics into code without generics.

在泛型类中,T被擦除到擦除其上限,在这种情况下是Object,但可以是其他的。对T的转换成为T的上限(在这种情况下是Object,所以它是多余的,编译器可能会跳过它)。该方法类似地返回T的上界(其为Object)。因此,没有运行时检查方法中的转换是否有效。

In the generic class, T gets erased to the erasure of its upper bound, which in this case is Object, but could be something else. The cast to T becomes a cast to T's upper bound (which in this case is Object, so it is redundant and the compiler might skip it). The method similarly returns T's upper bound (which is Object). So there is no runtime check that the cast is valid inside the method.

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的方法的地方,在这种情况下,在main方法中,你有一个 GenericClass ,所以当 getCast 返回T,它转换为Integer。所以在这种情况下,运行时检查现在被移动到调用方法,而不是具有转换的方法。

In the places that call the method that returns T, the compiler will insert a cast into the actual type of T. In this case, in the main method, you have a GenericClass<Integer>, so when getCast returns T, it is cast to Integer. So in this case the runtime check now gets "moved" to the calling method, not the method with the cast.

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

也可能调用者保留 GenericClass< S& code>引用(对于某些类型参数S在其作用域中),以便将结果转换为S,而不是特定类型。然后我们将重复整个重写过程(即对S的转换重写到一个转换的上限,并且调用该方法的地方将把结果转换为它们的实际类型参数)。这意味着运行时检查可能会推迟到另一个地方,等等。

It is also possible that the caller kept a GenericClass<S> reference (for some type parameter S in its scope), so that the result is cast to S, not a specific type. Then we would repeat the whole re-writing process again (i.e. the cast to S is re-written to a cast to its upper bound, and places that call into that method will cast the result to their actual type argument). This means that the runtime check might be deferred to yet another place, and so on.

这篇关于在Java运行时使用泛型 - (T)对象进行转换会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆