Явное совпадение имени Java, имеет одно и то же стирание, и не скрывает другого
Я получаю ошибку столкновения этого имени, и я не знаю, как решить проблему.
У меня есть два класса, и я использую перегруженный метод "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;
}
}
Ответы
Ответ 1
Общее решение - использовать разные имена. Эти методы могут быть в классах без отношения наследования, поскольку они не являются методами экземпляра.
Как указано, реализация метода в вопросе одинакова (исключение опечатки).
(Эта проблема с перегрузкой часто путается с стиранием типов времени выполнения. Перегрузка - это время связи, а не динамическая проблема, поэтому ее можно легко фиксировать на языке. Это просто не очень полезное изменение, а не хорошее идея поощрять перегрузку.)
Ответ 2
Общий ответ:
Помимо проблемы одной и той же реализации здесь, суть проблемы заключается в том, что несколько варварский "метод A и метод B имеют одно и то же стирание".
Что делает этот вопрос сложным, так это то, что мы, как правило, не (по крайней мере, не этим утром) много знаем о типе Erasure.
Чтобы сделать это коротко:
Параметрические типы выполняют проверку типа во время компиляции (для обеспечения правильности ввода), но забудьте о своих параметрах типа во время выполнения (чтобы избежать генерации базовых методов).
Звучит в то же время просто и загадочно.
Лучший способ понять это - обратиться к следующей литературе:
Надеюсь, что это поможет вам в той мере, в какой это помогло мне.
Конкретный ответ:
В вашем случае
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
}
}
будет преобразован 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
}
}
где один явно не может переопределить другой (не тот же самый параметр типа), но в то же время в точности совпадет во время выполнения (нет возможности для вашей программы выбрать, какой из них использовать).
Хватит этой проблемы, как ее решить?
Вы можете выполнить один из следующих способов:
-
Используйте разные имена: createASensors
и createBSensors
этот подход является наиболее очевидным, но выглядит немного менее изящным.
-
Добавьте параметр: createSensors(Collection<? extends ClassA> list, ClassA typeDefiner)
этот подход может показаться варварским, но немного менее изящным, но используется в java.util.List
для метода <T> T[] toArray(T[] a)
.
Ответ 3
Проверьте настройки проекта и версию компилятора проекта. Щелкните правой кнопкой мыши по проекту → Свойства → Компилятор Java. Убедитесь, что настройка соответствия обновлена. У меня была эта проблема, когда параметры соответствия были установлены на 1.4 вместо 1.6