如下所示的泛型方法:
static <E, K extends E> void someMethod(K k, E[] e) {}我推测在擦除时,擦除类型应该是:
static void someMethod(Object k, Object[] e) {}只是好奇在类型擦除之后,类型参数如何知道约束?类型参数K有界于E?
发布于 2011-07-28 12:15:46
你对擦除的看法是正确的。实际上,运行时并不知道这些约束。只有编译器才这样做。
发布于 2011-07-28 13:34:11
您已删除类型的签名是正确的。但是,方法的约束在编译期间不会被擦除。它们被编码在元数据中,在编译时使用(通常不会在运行时使用,尽管可以通过反射*访问)。例如,类java.util.ArrayList<E>具有以下方法:
public E get(int index)通过类型擦除,它变成了:
public Object get(int index)然而,在您的代码中,如果您使用String参数化ArrayList,那么您将调用get(...)方法,而不需要将结果强制转换为String,尽管存在类型擦除。
这与参数化类或方法调用时发生的情况不同。提供的参数化在编译时被完全擦除。例如:
ArrayList<String> myList = new ArrayList<String>();编译后相当于:
ArrayList myList = new ArrayList();*在运行时通过反射访问此信息可以通过使用返回java.lang.reflect.Type实例的反射方法来完成。例如,要在运行时获得方法的约束,可以调用java.lang.reflect.Method的getGenericParameterTypes()方法。处理这些返回的信息可以在运行时确定约束。
发布于 2011-07-30 16:48:49
我想指出的是,实际上,您的类型约束
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);他们不可能进一步限制它。
https://stackoverflow.com/questions/6853999
复制相似问题