简体   繁体   English

Java中的类型擦除

[英]Type erasure in Java

I had to process nested collections (for example, a map of lists or a map of maps) and that is the way I was going to handle it: 我必须处理嵌套的集合(例如,列表列表或地图列表),这就是我要处理的方式:

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

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

But I am told by the compiler that the above two methods have the same type erasure. 但是编译器告诉我,以上两种方法具有相同的类型擦除。 I wonder why, since I have specified different type bounds. 我不知道为什么,因为我指定了不同的类型界限。

The erasure of Map<?, ? extends Collection<?>> 删除Map<?, ? extends Collection<?>> Map<?, ? extends Collection<?>> is Map<Object, Object> Map<?, ? extends Collection<?>>Map<Object, Object>

The erasure of Map<?, ? extends Map<?, ?>> 删除Map<?, ? extends Map<?, ?>> Map<?, ? extends Map<?, ?>> is also Map<Object, Object> Map<?, ? extends Map<?, ?>>也是Map<Object, Object>

To understand why, you need to understand how how the erasure of Map is calculated. 要了解原因,您需要了解如何计算Map的删除量。 Basically, you take the type ( Map<K, V> ) and replace the formal type parameters (not the actual type parameters) with their respective least upper bound types. 基本上,您采用类型( Map<K, V> )并将形式类型参数(而不是实际类型参数)替换为其各自的最小上限类型。 In this case, the least upper bound type is Object for both K and V , since neither have any type constraints on them ... in the Map interface. 在这种情况下,最小的上限类型是KV Object ,因为在Map接口中它们都没有任何类型约束。

I think I might have made up the term "least upper bound type". 我想我可能已经编造了“最小上限类型”一词。 (Sorry) But what I mean is the most specific type that is not a subtype of any of the possible types in the set that are allowed. (对不起)但是我的意思是最具体的类型,它不是集合中允许的任何可能类型的子类型。


Another way to think of erasure is as follows. 考虑擦除的另一种方法如下。 Consider this class: 考虑此类:

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

Now imagine that we had to express that without using generics. 现在想象一下,我们必须不使用泛型来表达这一点。 What actual type would we use in place of T ? 我们将使用什么实际类型代替T In this case, it would be Object . 在这种情况下,它将是Object

And in fact, when a generic type is mapped to a runtime type, that is exactly what happens! 而事实上,当一个泛型类型映射到运行时类型,这正是发生了什么!


But, basically, you won't be able to create overloads of a method that differ only on the type parameterization of a Map type. 但是,基本上,您将无法创建仅在Map类型的类型参数化方面不同的方法重载。 Unless you reify the types: 除非您更改类型:

  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) {
     ...
  }

.... which is ugly, to say the least. ....至少可以说很难看。

Solution: use different method names instead of trying to overload the same name. 解决方案:使用不同的方法名称,而不要尝试重载相同的名称。

Cannot overload a method where the formal parameter types of each overload erase to the same raw type. 无法重载每个重载的形式参数类型都擦除为相同原始类型的方法。

In your code, both method have the same signature after type erasure: 在您的代码中,两个方法在类型擦除后具有相同的签名:

public static String doSomething(Map map);

To solve your problem, you can use just two different method names instead of overloading the method. 要解决您的问题,您可以仅使用两个不同的方法名称,而不必重载该方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM