泛型方法按如下:泛型方法有限制类型参数和类型擦除
static <E, K extends E> void someMethod(K k, E[] e) {}
我擦除时认为,擦除类型是:
static void someMethod(Object k, Object[] e) {}
只是好奇,怎么会有类型参数知道类型擦除后的约束?那个类型参数K是有界的E?
泛型方法按如下:泛型方法有限制类型参数和类型擦除
static <E, K extends E> void someMethod(K k, E[] e) {}
我擦除时认为,擦除类型是:
static void someMethod(Object k, Object[] e) {}
只是好奇,怎么会有类型参数知道类型擦除后的约束?那个类型参数K是有界的E?
你对擦除是正确的。实际上,运行时并不知道约束条件。只有编译器才会。
您的类型擦除签名是正确的。但是,编译过程中方法的约束不会被擦除。它们被编码在编译时使用的元数据中(并且通常在运行时使用,尽管它可以通过反射*进行访问)。例如,类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
的getGenericParameterTypes()
方法。处理这些返回的信息可以在运行时确定约束条件。
我要指出的是,其实,你的类型约束
static <E, K extends E> void someMethod(K k, E[] e) {}
有完全相同相同的效果(在编译时)作为
static void someMethod(Object k, Object[] e) {}
尝试调用someMethod("foo", new Integer[3])
如果你不”不相信我。
这是因为它是有效的,编译器推断Object
作为既E
和K
(参数,因为任何K
对象也是Object
一个实例,任何E[]
对象也是Object[]
一个实例(记住,阵列类型在Java中是协变的))。
这是Java泛型中常见的错误。例如,Arrays.fill()
方法的签名为static void fill(Object[] a, Object val)
;他们不可能进一步限制它。
否则它不会被非常消除。 –