在Java中键入擦除

时间:2017-01-17 09:50:18

标签: java collections type-conversion type-erasure

我必须处理嵌套集合(例如,列表地图或地图地图),这就是我要处理它的方式:

  public static String doSomething(Map<?, ? extends Collection<?>> map) {
     ...
  }

  public static String doSomething(Map<?, ? extends Map<?, ?>> map) {
     ...
  }

但编译器告诉我,上述两种方法具有相同类型的擦除。我想知道为什么,因为我已经指定了不同的类型边界。

2 个答案:

答案 0 :(得分:3)

Map<?, ? extends Collection<?>>的删除是Map<Object, Object>

Map<?, ? extends Map<?, ?>>的删除也是Map<Object, Object>

要了解原因,您需要了解如何计算Map的擦除方式。基本上,您采用类型(Map<K, V>)并将形式类型参数(而不是实际类型参数)替换为各自的最小上限< / em>类型。在这种情况下,ObjectK的最小上限类型为V,因为它们在Map接口中都没有任何类型约束。 / p>

我想我可能已经编造了一个术语&#34;最小上限类型&#34;。 (抱歉)但我的意思是最具体的类型,它不是允许的集合中任何可能类型的子类型。

另一种考虑擦除的方法如下。考虑这个课程:

public class Test <T> {
    public set(T t):
}

现在想象一下,我们必须在不使用泛型的情况下表达这一点。我们将使用什么实际类型代替T?在这种情况下,它将是Object

事实上,当泛型类型映射到运行时类型时,完全会发生什么!

但是,基本上,您无法创建仅在Map类型的类型参数化方面不同的方法的重载。除非您重新确定类型:

  public class X implements Map<String, Integer> ...

  public class Y implements Map<String, Double> ...

  public static String doSomething(X map) {
     ...
  }

  public static String doSomething(Y map) {
     ...
  }

......至少可以说是丑陋的。

解决方案:使用不同的方法名称,而不是尝试重载相同的名称。

答案 1 :(得分:2)

不能重载每个重载的形式参数类型擦除到相同原始类型的方法。

在您的代码中,两种方法在类型擦除后都具有相同的签名:

public static String doSomething(Map map);

要解决您的问题,您只能使用两个不同的方法名称,而不是重载方法。