通用方法有界类型参数和类型擦除

时间:2011-07-28 04:12:29

标签: java generics

如下通用方法:

static <E, K extends E> void someMethod(K k, E[] e) {}

我推测擦除时,擦除类型将是:

static void someMethod(Object k, Object[] e) {}

好奇的是,类型参数在类型擦除后如何知道约束?该类型参数K与E?

有界

3 个答案:

答案 0 :(得分:8)

你对删除是正确的。实际上,运行时不知道约束。只有编译器才能这样做。

答案 1 :(得分:2)

您的类型删除签名是正确的。但是,在编译期间不会擦除方法的约束。它们编码在编译时使用的元数据中(虽然可以通过反射*访问,但通常不会在运行时使用)。例如,类java.util.ArrayList<E>具有以下方法:

public E get(int index)

哪种类型擦除变为:

public Object get(int index)

但是,在您的代码中,如果您使用ArrayList参数化String,那么您将调用get(...)方法,而无需将结果转换为String,尽管类型擦除。

这与参数化类或方法调用时发生的情况不同。提供的参数化 在编译时完全擦除。例如:

ArrayList<String> myList = new ArrayList<String>();

编译后相当于:

ArrayList myList = new ArrayList();

*通过反射在运行时访问此信息可以通过使用返回java.lang.reflect.Type实例的反射方法来完成。例如,要在运行时获取方法的约束,可以调用java.lang.reflect.Method的{​​{1}}方法。处理此返回的信息可以在运行时确定约束。

答案 2 :(得分:2)

我想注意,事实上,你的类型约束

static <E, K extends E> void someMethod(K k, E[] e) {}

具有相同的效果(在编译时)

static void someMethod(Object k, Object[] e) {}

如果您不相信我,请尝试拨打someMethod("foo", new Integer[3])

这是因为编译器推断Object作为EK的参数是有效的(因为任何K对象也是{的一个实例{1}},任何Object对象也是E[]的实例(请记住数组类型在Java中是协变的))。

这是Java Generics中常见的陷阱。例如,Object[]方法具有签名Arrays.fill();他们不可能进一步限制它。