Ява имя столкновения, имеют то же самое стирание, ни один не скрывает другой

Я получаю сообщение об ошибке "конфликт имен", и я не знаю, как мне решить эту проблему. У меня есть два класса, и я использую перегруженный метод "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;
   }
}

3 ответа

Решение

Общее решение - использовать разные имена. Эти методы могут быть в классах без отношения наследования, поскольку они не являются методами экземпляра.

Как указано, реализация метода в вопросе одинакова (опечатка исключена).

(Эта проблема с перегрузкой часто путается со стиранием типов времени выполнения. Перегрузка - это проблема времени соединения, а не динамическая проблема, поэтому ее можно легко исправить в языке. Это просто не особенно полезное изменение и не очень хорошая идея поощрять перегрузка.)

Общий ответ:

Помимо проблемы той же реализации здесь, ядро ​​проблемы состоит в том, что, несколько варварский, "метод A и метод B имеют одинаковое стирание".

Что усложняет вопрос, так это то, что мы, как правило, не знаем (по крайней мере, сегодня утром) о "стирании типов".

Чтобы сделать это коротким:

Параметрические типы выполняют проверку типа во время компиляции (для обеспечения правильности типа), но забывают свои параметры типа во время выполнения (чтобы избежать генерации базовых методов).

Это звучит одновременно просто и загадочно. Лучший способ понять это - обратиться к следующей литературе:

  1. Что такое тип reifiable?
  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
   }
}

будет "преобразован" Джаваком в

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
   }
}

где одно явно не может переопределить другое (не один и тот же параметр типа), но в итоге во время выполнения становится точно таким же (ваша программа не может выбрать, какой использовать).

Достаточно этой проблемы, как ее решить? Вы можете перейти к одному из следующих подходов:

  • Используйте разные имена: createASensors а также createBSensorsэтот подход является наиболее очевидным, но может показаться немного менее элегантным.

  • Добавьте параметр: createSensors(Collection<? extends ClassA> list, ClassA typeDefiner)этот подход может показаться варварским, но он немного менее элегантен, но используется в java.util.List для метода <T> T[] toArray(T[] a),

Проверьте настройки проекта и версию компилятора проекта. Щелкните правой кнопкой мыши по проекту -> Свойства -> Компилятор Java. Убедитесь, что настройки соответствия обновлены. У меня была эта проблема, когда параметры соответствия были установлены на 1,4 вместо 1,6

Другие вопросы по тегам