Java名称冲突,具有相同的擦除,既不隐藏另一个

use*_*246 18 java generics name-clash

我得到这个名字冲突错误,我不知道我应该如何解决这个问题.我有两个类,我使用重载方法"createSensors".这里简化的是生成问题的代码:

public abstract class ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
        List<Sensor> sensors = new ArrayList<Sensor>();
        for (ClassA s : list) {
           sensors.add(s.getSensor());
        }
        return sensors;
    }
}

public abstract class ClassB extends ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
        List<Sensor> sensors = new ArrayList<Sensor>();
        for (ClassB s : list) {
           sensors.add(s.getSensor());
        }
        return sensors;
   }
}
Run Code Online (Sandbox Code Playgroud)

Ar3*_*r3s 13

一般答案:

除了这里相同实现的问题之外,问题的核心是,有些野蛮,"方法A和方法B具有相同的擦除".

使它成为一个复杂问题的原因是我们通常不会(至少我今天早上没有)对"类型擦除"有很多了解.

简而言之:

参数类型在编译时执行类型检查(以确保类型正确性)但在运行时忘记它们的类型参数(以避免生成基础方法).

这听起来简单而令人费解.理解它的最佳方式是参考以下文献:

  1. 什么是可再生类型?
  2. 如何以及在什么条件下进行擦除?
  3. 关于它在我的编码生活中可能意味着什么,你有什么想法/例子吗?
  4. 嗯,这很奇怪,我不喜欢它,但我很好奇为什么他们这样做...

希望能帮助你,帮助我.

具体答案:

在你的情况下

public abstract class ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
        //do stuff
    }
}

public abstract class ClassB extends ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
        //do other stuff
   }
}
Run Code Online (Sandbox Code Playgroud)

将由javac"改造"为

public abstract class ClassA {
    public static List createSensors(Collection list) {
        //do stuff
    }
}

public abstract class ClassB extends ClassA {
    public static List createSensors(Collection list) {
        //do other stuff
   }
}
Run Code Online (Sandbox Code Playgroud)

其中一个显然不能覆盖另一个(不是相同的类型参数)但最终在运行时完全相同(您的程序无法选择使用哪一个).

够了这个问题,怎么解决呢?您可以继续使用以下方法之一:

  • 使用不同的名称:createASensors而且createBSensors 这种方式是最明显的,但似乎有点不太优雅.

  • 添加一个参数:createSensors(Collection<? extends ClassA> list, ClassA typeDefiner) 这种方法看似野蛮,但不太优雅,但是java.util.List用于该方法的方法<T> T[] toArray(T[] a).

  • 你的回答很好地解释了这一点。但我想知道您是否也可以解释为什么编译的行为是这样的,以及为什么我们不能简单地通过它们的实际类来调用方法来区分它们;ClassA.createSensors(...) ClassB.createSensors(...) (2认同)

Tom*_*ine 5

一般的解决方案是使用不同的名称.这些方法可以在没有继承关系的类中,因为它们不是实例方法.

正如所指出的,问题中的方法实现是相同的(错误除外).

(这个重载问题经常与删除运行时类型混淆.重载是一个链接时间而不是动态问题,所以可以很容易地用语言修复.这不是一个特别有用的改变,也不是一个好主意鼓励超载).