JDK 1.7 нарушает обратную совместимость? (генерики)
Я нашел похожие темы, но слишком сложные и не совсем то же самое. Так и есть. Здесь (минимальный) код, который хорош на 1.6, но не компилируется с 1.7 javac.
public class Test {
private static class A<T>{};
private static class B{};
private static class C{};
B doSomething(A<B> arg){
return new B();
}
C doSomething(A<C> arg){
return new C();
}
}
В 1.7 ошибка:
java: name clash: doSomething(Test.A<Test.C>) and doSomething(Test.A<Test.B>) have the same erasure
Я понимаю стирание типа и почему это неправильный код. Я просто не понимаю, почему мы можем иметь этот код в нашем проекте, который компилируется и работает в версии 1.6, когда у 1.7 есть проблемы с ним. Что не так? Это ошибка в компиляторе 1.6, которая позволяет нам это сделать? Можно ли заставить его работать в 1,7, кроме перезаписи?
- JDK1.6 версия javac: 1.6.0_43
- JDK1.7 версия javac: 1.7.0_25
Ответы
Ответ 1
Вы совершенно правы, под JLS3 этот код никогда не должен компилироваться, и это было ошибкой в 1.6.
Для выпуска 1,7 большая часть базовой системы типов была обновлена, и эта ошибка была исправлена, результатом стала улучшенная обработка типов за счет некоторых проблем с обратной совместимостью.
Что касается того, чтобы заставить его работать в 1.7, я считаю, что повторный факторинг - это ваш единственный вариант.
Ответ 2
Это одна из ошибок в javac, которые были исправлены в Java 7 - вы можете найти дополнительную информацию в примечаниях к выпуску . Я боюсь, что ваш единственный вариант - переписать этот код, если вы хотите переключиться на Java 7.
Область: Инструменты
Синопсис: класс не может определить два метода с одинаковой стираемой подписью, но два разных типа возврата
Описание. Класс не может определить два метода с одинаковой стертой сигнатурой, независимо от того, являются ли типы возврата одинаковыми или нет. Это следует из JLS, Java SE 7 Edition, раздел 8.4.8.3. Компилятор JDK 6 позволяет использовать методы с одинаковой стираемой подписью, но с разными типами возврата; это неправильное поведение и было исправлено в JDK 7.
Пример:
class A {
int m(List<String> ls) { return 0; }
long m(List<Integer> ls) { return 1; }
}
Этот код компилируется под JDK 5.0 и JDK 6 и отклоняется в JDK 7.