Есть ли конкретные примеры обратной несовместимости между версиями Java?

Были ли несовместимости между выпусками Java, в которых исходный код Java / файлы классов Java, нацеленные на версию Java X, не компилируются / запускаются под версией Y (где Y> X)?

Под «выпуском Java» я подразумеваю такие версии, как:

  • JDK 1.0 (январь 1996 г.)
  • JDK 1.1 (февраль 1997 г.)
  • J2SE 1.2 (декабрь 1998 г.)
  • J2SE 1.3 (май 2000 г.)
  • J2SE 1.4 (февраль 2002 г.)
  • J2SE 5.0 (сентябрь 2004 г.)
  • Java SE 6 (декабрь 2006 г.)

Домашние правила:

  • По возможности включите ссылки и примеры кода.
  • Пожалуйста, постарайтесь быть очень конкретным / конкретным в своем ответе.
  • Класс, помеченный как @Deprecated, не считается обратной несовместимостью.

person knorv    schedule 31.10.2009    source источник
comment
Вы имеете в виду "отсутствие ответа хуже, чем чрезмерно расплывчатый ответ"   -  person Egwor    schedule 31.10.2009
comment
это определенно должна быть вики сообщества   -  person dfa    schedule 31.10.2009
comment
Почему? Совершенно законный технический вопрос ...   -  person bdonlan    schedule 31.10.2009
comment
Это может быть технический характер, но это не тот вопрос, который вы задаете, потому что вам ›› нужно ‹*******************************************   -  person Stephen C    schedule 01.11.2009
comment
Стивен К .: Мне нужно знать ответ.   -  person knorv    schedule 01.11.2009
comment
knorv, противно, если я спрошу почему? Если есть конкретная область, где обратная совместимость вызывает беспокойство, возможно, мы сможем быть более полезными.   -  person Sean Reilly    schedule 04.11.2009
comment
@Sean: Хорошая причина необходимости узнать этот ответ - это отстаивать выбор java против .NET или php или любой конкурирующей технологии для данного проекта, в котором обратная совместимость обязательна.   -  person ZJR    schedule 13.01.2010


Ответы (14)


Примечания по совместимости для различных версий:

Первой серьезной ошибкой, которую я помню, было введение assert в Java 1.4. Это повлияло на большую часть кода JUnit.

person McDowell    schedule 31.10.2009
comment
Введение новых, зарезервированных ключевых слов должно строго караться! И они сделали это снова с помощью enum. - person Thorbjørn Ravn Andersen; 31.10.2009
comment
И все же они никогда не удаляли goto как зарезервированное слово! - person Duncan McGregor; 05.11.2009
comment
Интересно, что в официальных заметках нет комментариев о несовместимости пакета JDBC. Или я это пропустил? - person tangens; 09.11.2009
comment
@tangens - вероятно, не отмечено, потому что код клиента JDBC не нужно будет изменять для работы с новым API; Приложения Java обычно не реализуют эти интерфейсы; поставщики баз данных сделают это. Вы можете найти конкретную информацию в тегах @since в javadoc и, вероятно, более подробно в спецификации JDBC: java.sun.com/products/jdbc/download.html - person McDowell; 09.11.2009

Во-первых, Sun на самом деле считает все упомянутые вами выпуски (кроме 1.0, конечно) второстепенными, а не основными.

Я не знал ни одного примера бинарной несовместимости в то время. Однако было несколько примеров несовместимости источников:

  • В Java 5 «enum» стало зарезервированным словом; этого не было раньше. Следовательно, были исходные файлы, которые использовали enum в качестве идентификатора, который будет компилироваться в java 1.4, но не будет компилироваться в java 5.0. Однако вы можете скомпилировать с -source 1.4, чтобы обойти это.

  • Добавление методов в интерфейс также может нарушить совместимость исходного кода. Если вы реализуете интерфейс, а затем попытаетесь скомпилировать эту реализацию с помощью JDK, который добавляет новые методы к интерфейсу, исходный файл больше не будет успешно компилироваться, поскольку он не реализует все члены интерфейса. Это часто происходило с java.sql.Statement и другими интерфейсами jdbc. Скомпилированные формы этих «недействительных» реализаций будут работать до тех пор, пока вы не вызовете один из несуществующих методов; если вы это сделаете, будет выброшено исключение MissingMethodException.

Это несколько примеров, которые я могу припомнить, но могут быть и другие.

person Sean Reilly    schedule 31.10.2009
comment
Хуже всего было то, что некоторые из методов, добавленных в интерфейсы JDBC, основывались на новых типах, которых не было в более ранних версиях. Это означало, что было невозможно создать реализации, которые могли бы компилироваться в нескольких версиях JDK. - person Laurence Gonsalves; 31.10.2009
comment
Я сам столкнулся с этим снова на прошлой неделе на работе. В итоге мы прибегли к написанию динамического прокси, чтобы получить реализацию, которая будет компилироваться как на Java 5, так и на 6. - person Sean Reilly; 31.10.2009

Интерфейс java.sql.Connection был расширен с Java 1.5 до Java 1.6, что привело к сбою компиляции всех классов, реализующих этот интерфейс.

person tangens    schedule 31.10.2009
comment
Я думаю, что все версии JDBC широко это делают. Это не должно быть сюрпризом! - person Tom Hawtin - tackline; 31.10.2009
comment
И снова с JDK 1.8. - person Menachem; 24.05.2018

Каждый выпуск Swing с 1.3 по 1.6 что-то ломал для нас.

Проблема JDBC уже упоминалась, но существующий код работал.

С 1.5 до 1.6 было изменение в поведении Socket, которое нарушало работу клиента Cisco.

Конечно, были введены новые зарезервированные ключевые слова.

Самым большим, что я считаю непростительным для Sun, был System.getenv (). Он работал в версии 1.0, а затем был объявлен устаревшим и изменен, чтобы выдавать ошибку на всех платформах под довольно сомнительным оправданием, что у Mac не было системных переменных среды. Затем Mac получил системные переменные среды, поэтому в 1.5 он не был рекомендован и работает. Для этого нет разумного оправдания. Верните пустой набор на Mac (у Swing гораздо большие проблемы с кроссплатформенностью, если вы хотите позаботиться об этом уровне согласованности между платформами) или даже на всех платформах.

Я никогда не соглашался с тем, чтобы они отключили эту функцию, но изменить ее так, чтобы она выдавала ошибку, было просто критическим изменением, которое, если бы они собирались это сделать, им следовало бы просто полностью удалить метод.

Но на самом деле с 1.0 до 1.1 их меньше беспокоила обратная совместимость. Например, они отказались от модификатора «частный защищенный».

Итак, в результате каждая версия меняется настолько, что требует тщательной оценки, поэтому вы все еще видите много вопросов о 1.4 здесь, о SO.

person Yishai    schedule 01.11.2009

Главное, что я могу придумать, - это введение новых зарезервированных слов:

Java 1.3: strictfp
Java 1.4: assert
Java 5.0: enum

Любой код, который ранее использовал эти значения в качестве идентификаторов, не будет компилироваться в более поздней версии.

Еще одна проблема, которую я помню, вызывала проблемы в проекте, над которым я работал, заключалась в том, что было изменение видимости JInternalFrames по умолчанию между 1.2 и 1.3. По умолчанию они были видны, но когда мы обновились до 1.3, казалось, что все они исчезли.

person Dan Dyer    schedule 31.10.2009
comment
Может быть, было бы разумно, если бы они зарезервировали несколько ключевых слов, которые могут быть использованы в будущем, даже если это не определенно. Такие слова, как struct и function, на данный момент являются действительными идентификаторами. - person Bart van Heukelom; 26.07.2011

Между 1.3 и 1.4 интерпретация Long.parseLong (String) обрабатывала пустую строку по-разному. 1.3 возвращает значение 0, тогда как 1.4 возвращает NumberFormatException.

Перекомпиляция не требуется, но рабочий код переставал работать, если он полагался на поведение 1.3.

person rsp    schedule 31.10.2009

Семантика модели памяти изменено с 1,4 на 1,5. Он был изменен, чтобы, помимо прочего, снова разрешить блокировку с двойной проверкой. (Я думаю, что изменчивая семантика была исправлена.) Она была нарушена.

person Thomas Jung    schedule 31.10.2009
comment
Это изменение, но как код в 1.4 переходит на 1.5? Мне кажется, обратная совместимость. - person Yishai; 06.11.2009

Следующее будет компилироваться под Java 1.4, но не Java 1.5 или новее.

(В Java 5 введено ключевое слово enum. Примечание: он будет компилироваться в Java 5, если указан параметр «-source 1.4».)

public class Example {
    public static void main(String[] args) {
        String enum = "hello";
    }
}
person Michael Easter    schedule 31.10.2009

Очевидно, что соглашение об именах названий выпусков выглядит следующим образом: не имеет обратной совместимости.

  • JDK 1.0 (23 января 1996 г.)
  • JDK 1.1 (19 февраля 1997 г.)
  • J2SE 1.2 (8 декабря 1998 г.)
  • J2SE 1.3 (8 мая 2000 г.)
  • J2SE 1.4 (6 февраля 2002 г.)
  • J2SE 5.0 (30 сентября 2004 г.)
  • Java SE 6 (11 декабря 2006 г.)
  • Java SE 6 (обновление 10, обновление 12, обновление 14, обновление 16)
  • Java SE 7 ??? JDK7?

(Список взят из Википедии.)

person Andreas Petersson    schedule 31.10.2009

Еще один пример нарушения совместимости java.sql:

В версии 1.5 к java.sql.Timestamp был добавлен метод compareTo (Date). Этот метод вызовет исключение ClassCastException, если предоставленная Date не является экземпляром java.sql.Timestamp. Конечно, java.sql.Timestamp расширяет Date, а Date уже имел метод compareTo (Date), который работал со всеми датами, поэтому это означало, что код, сравнивающий метку времени с датой (без метки времени), сломается во время выполнения в 1.5. .

Интересно отметить, что похоже, что версия 1.6 решила эту проблему. Хотя документация для java.sql.Timestamp.compareTo (Date) по-прежнему говорит: «Если аргумент не является объектом Timestamp, этот метод генерирует объект ClassCastException», фактическая реализация говорит об обратном. Я предполагаю, что это ошибка документации.

person Laurence Gonsalves    schedule 31.10.2009

См. Отчет об изменениях API для библиотеки классов JRE здесь: http://abi-laboratory.pro/java/tracker/timeline/jre/

Отчет включает обратный анализ двоичной и исходной совместимости классов Java.

Отчет создается japi-compliance-checker орудие труда.

введите здесь описание изображения

...

введите здесь описание изображения

Еще один интересный анализ JDK 1.0-1.6 вы можете найти по адресу Japitools JDK-Results страница.

person linuxbuild    schedule 07.01.2011

Как сказал Шон Рейли, новый метод может сломать ваш код. Помимо простого случая, когда вам нужно реализовать новый метод (это приведет к предупреждению компилятора), есть и худший случай: новый метод в интерфейсе имеет ту же сигнатуру, что и метод, который у вас уже есть. в вашем классе. Единственный намек от компилятора - это предупреждение об отсутствии аннотации @Override (Java 5 для классов, аннотация поддерживается для интерфейсов в Java 6, но не является обязательной).

person Thomas Jung    schedule 31.10.2009
comment
Обходной путь: никогда не делайте метод общедоступным, если он не реализует или не переопределяет метод интерфейса (не так сложно, как может показаться - я придерживаюсь этого правила уже несколько лет). - person finnw; 03.11.2009

Я не пробовал, но теоретически это сработает в Java 1.1 и сломается в Java 1.2. (Подробнее здесь)

public class Test {
    float strictfp = 3.1415f;
}
person Michael Easter    schedule 31.10.2009

По личному опыту, у нас были некоторые текстовые поля AWT / Swing, встроенные во фрейм SWT_AWT в 1.5, которые перестали быть редактируемыми после обновления до 1.6.

person Chris    schedule 05.11.2009