【问题标题】:Generic method bounded type parameter and type erasure泛型方法有界类型参数和类型擦除
【发布时间】:2011-07-28 04:12:28
【问题描述】:

通用方法如下:

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

我假设在擦除时,擦除类型是:

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

只是好奇类型参数如何知道类型擦除后的约束?那个类型参数 K 有界到 E?

【问题讨论】:

    标签: java generics


    【解决方案1】:

    您对擦除的看法是正确的。实际上,运行时不知道约束。只有编译器会这样做。

    【讨论】:

    • 否则不会很擦除。
    【解决方案2】:

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

    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.MethodgetGenericParameterTypes() 方法。处理这个返回的信息可以在运行时确定约束。

    【讨论】:

      【解决方案3】:

      我想指出,事实上,你的类型约束

      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 对象也是Object 的实例,并且任何E[] object 也是 Object[] 的一个实例(记住数组类型在 Java 中是协变的)。

      这是 Java 泛型中的一个常见缺陷。例如Arrays.fill()方法有签名static void fill(Object[] a, Object val);他们不可能进一步限制它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-01
        • 1970-01-01
        相关资源
        最近更新 更多