方法与类型中的另一种方法具有相同的擦除 [英] Method has the same erasure as another method in type

查看:892
本文介绍了方法与类型中的另一种方法具有相同的擦除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class Test {
void}为什么在同一个类中使用这两种方法是不合法的? add(Set< Integer> ii){}
void add(Set< String> ss){}
}

我得到编译错误


方法添加(Set)与Test类型中的另一种方法具有相同的擦除添加(Set)。


当我可以解决它时,我想知道为什么javac不喜欢这个。



我可以看到,在很多情况下,这两种方法的逻辑非常相似,可以用一个单一的

  public void add(Set<?> set){} 
pre>

方法,但并非总是如此。



如果您想要两个构造函数,它们接受这些参数,因为那样你就不能只改变一个构造函数的名称。 p>

解决方案

这个规则是为了避免仍然使用原始类型的遗留代码中的冲突。



是不允许的,从JLS。假设在泛型引入Java之前,我编写了如下代码:

  class CollectionConverter { b $ b List toList(Collection c){...} 
}

我的类,如下所示:

 类Overrider扩展了CollectionConverter {
List toList(Collection c){...}
}

在引入泛型后,我决定更新我的库。

  class CollectionConverter {
< T>列表与LT; T> toList(Collection< T> c){...}
}

准备好进行任何更新,因此您只需保留 Overrider 类。为了正确地覆盖 toList()方法,语言设计者认为原始类型与任何基因型类型是覆盖等价。这意味着,尽管您的方法签名不再与我的超类签名正式相同,但您的方法仍然会覆盖。



现在,时间过去了,您决定准备好更新你的班。但是你搞砸了一点,而不是编辑现有的原始 toList()方法,你可以添加一个像这样的新方法: p>

 类Overrider扩展了CollectionConverter {
@Override
List toList(Collection c){...}
@Override
< T>列表与LT; T> toList(Collection< T> c){...}
}

覆盖原始类型的等价性,这两种方法都以有效的形式覆盖 toList(Collection 方法。但是,当然,编译器需要解决一个方法。为了消除这种歧义,类不允许有多个方法,这些方法是与override等效的方法 - 也就是说,擦除后具有相同参数类型的多个方法。



关键是这是一种语言规则,旨在保持与使用原始类型的旧代码的兼容性。这不是擦除类型参数所要求的限制;因为方法解析发生在编译时,所以在方法标识符中添加泛型类型就足够了。

Why is it not legal to have those two methods in the same class?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

I get the compilation error

Method add(Set) has the same erasure add(Set) as another method in type Test.

while I can work around it, I was wondering why javac doesn't like this.

I can see that in many cases, the logic of those two methods would be very similar and could be replaced by a single

public void add(Set<?> set){}

method, but this is not always the case.

This is extra annoying if you want to have two constructors that takes those arguments because then you can't just change the name of one of the constructors.

解决方案

This rule is intended to avoid conflicts in legacy code that still uses raw types.

Here's an illustration of why this was not allowed, drawn from the JLS. Suppose, before generics were introduced to Java, I wrote some code like this:

class CollectionConverter {
  List toList(Collection c) {...}
}

You extend my class, like this:

class Overrider extends CollectionConverter{
  List toList(Collection c) {...}
}

After the introduction of generics, I decided to update my library.

class CollectionConverter {
  <T> List<T> toList(Collection<T> c) {...}
}

You aren't ready to make any updates, so you leave your Overrider class alone. In order to correctly override the toList() method, the language designers decided that a raw type was "override-equivalent" to any generified type. This means that although your method signature is no longer formally equal to my superclass' signature, your method still overrides.

Now, time passes and you decide you are ready to update your class. But you screw up a little, and instead of editing the existing, raw toList() method, you add a new method like this:

class Overrider extends CollectionConverter {
  @Override
  List toList(Collection c) {...}
  @Override
  <T> List<T> toList(Collection<T> c) {...}
}

Because of the override equivalence of raw types, both methods are in a valid form to override the toList(Collection<T>) method. But of course, the compiler needs to resolve a single method. To eliminate this ambiguity, classes are not allowed to have multiple methods that are override-equivalent—that is, multiple methods with the same parameter types after erasure.

The key is that this is a language rule designed to maintain compatibility with old code using raw types. It is not a limitation required by the erasure of type parameters; because method resolution occurs at compile-time, adding generic types to the method identifier would have been sufficient.

这篇关于方法与类型中的另一种方法具有相同的擦除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆