为什么我不能在Java中为单个类定义这两个构造函数?

时间:2014-05-18 04:54:33

标签: java constructor type-erasure

我正在为一个类定义一个构造函数,我有这两个定义:

MyClass(Set<ClassA> setOfA) { ... }

MyClass(Set<ClassB> setOfB) { ... }

我收到以下错误:

MyClass(java.util.Set<ClassA>) is already defined in MyClass
    MyClass(Set<ClassB> setOfB)

如果我特意将其中一个设为HashSet而不是Set,则代码会编译。为什么呢?

3 个答案:

答案 0 :(得分:7)

如果你有

MyClass(Set<A> setOfA) { ... }

MyClass(Set<B> setOfB) { ... }

类型擦除将它们转换为:

MyClass(Set setOfA) { ... }

MyClass(Set setOfB) { ... }

所以现在他们是一样的,编译器很困惑。

但是,如果其中一个是HashSet,那么你最终会得到这个:

MyClass(Set setOfA) { ... }

MyClass(HashSet setOfB) { ... }

现在它们与编译器完全不同,以确定在编译时绑定哪个。

答案 1 :(得分:5)

由于 type erasure ,Java编译器将(根据Java文档):

  
      
  • 将泛型类型中的所有类型参数替换为其边界,如果类型参数无界,则替换Object ...
  •   
  • 如有必要,插入类型转换以保护类型安全。
  •   
  • 生成桥接方法以保留扩展泛型类型中的多态性。
  •   

换句话说,Java编译器将convert the code to

MyClass(Set setOfA) { ... }

MyClass(Set setOfB) { ... }

所以两者都有相同的参数。这是导致错误的原因。

答案 2 :(得分:3)

这里的问题是所谓的&#34;类型擦除&#34;。简而言之,这意味着在编译代码后,泛型类型实际上并不存在,因此您的两个构造函数签名MyClass(Set<A>)MyClass(Set<B>)都看起来像MyClass(Set)。

可以在此处找到Oracle的相关说明:http://docs.oracle.com/javase/tutorial/java/generics/erasure.html