Существуют ли какие-либо конкретные примеры обратной несовместимости между версиями Java?

StackOverflow https://stackoverflow.com/questions/1654923

Вопрос

Были ли несовместимости между выпусками Java, когда файлы исходного кода Java / Java class, предназначенные для 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, не считается обратной несовместимостью.
Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

Каждый релиз Swing что-то ломал для нас, начиная с 1.3 по 1.6.

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

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

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

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

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

Но на самом деле с 1.0 по 1.1 они были меньше обеспокоены обратной совместимостью.Например, они отбросили "private protected" в качестве модификатора.

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

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

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

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

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

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

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

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

Следующее будет скомпилировано под 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";
    }
}

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

  • 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?

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

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

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

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

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

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

Отчет генерируется с помощью japi-проверка соответствия требованиям инструмент.

enter image description here

...

enter image description here

Другой интересный анализ для JDK 1.0-1.6 вы можете найти по адресу Japitools JDK-Результаты Страница.

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

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

public class Test {
    float strictfp = 3.1415f;
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top