通用方法有界类型参数和类型擦除
一种通用方法如下:
static void someMethod(K k, E[] e) {}
我推测擦除,擦除类型将是:
static void someMethod(Object k, Object[] e) {}
只是好奇类型参数在类型擦除后如何知道约束? 那个类型参数K被限制在E?
你对删除是正确的。 实际上,运行时不知道约束。 只有编译器才有。
您的类型删除签名是正确的。 但是,编译期间不会擦除方法的约束。 它们编码在编译时使用的元数据中(虽然可以通过reflection*访问,但通常不会在运行时使用)。 例如,类java.util.ArrayList
具有以下方法:
public E get(int index)
哪种类型擦除成为:
public Object get(int index)
但是,在您的代码中,如果使用String
参数化ArrayList
,那么您将调用get(...)
方法,而不需要将结果转换为String
尽管类型擦除。
这与参数化类或方法调用时发生的情况不同。 提供的参数化在编译时完全擦除。 例如:
ArrayList myList = new ArrayList ();
编译后相当于:
ArrayList myList = new ArrayList();
*通过reflection在运行时访问此信息可以通过使用返回java.lang.reflect.Type
实例的reflection方法来完成。 例如,要在运行时获取方法的约束,可以调用java.lang.reflect.Method
的getGenericParameterTypes()
方法。 处理此返回的信息可以在运行时确定约束。
我想要注意的是,事实上,你的类型约束
static void someMethod(K k, E[] e) {}
具有完全相同的效果(在编译时)
static void someMethod(Object k, Object[] e) {}
如果你不相信我someMethod("foo", new Integer[3])
试着调用someMethod("foo", new Integer[3])
。
这是因为编译器推断Object
作为E
和K
的参数是有效的(因为任何K
对象也是Object
的实例,并且任何E[]
对象也是Object[]
的实例(记住该数组)类型在Java中是协变的))。
这是Java Generics中常见的陷阱。 例如, Arrays.fill()
方法具有签名static void fill(Object[] a, Object val)
; 他们不可能进一步限制它。