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

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

В разделе "Java release" я подразумеваю такие версии, как:

  • 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, не считается обратной совместимостью.

Ответ 2

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

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

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

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

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

Ответ 3

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

Ответ 4

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

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

От 1,5 до 1,6 произошли изменения в поведении Socket, которые сломали клиента Cisco.

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

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

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

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

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

Ответ 5

Основной, о котором я могу думать, это введение новых зарезервированных слов:

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

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

(Java 5 вводит "enum" в качестве ключевого слова. Примечание: он будет скомпилирован в Java 5, если предоставляется опция "-источник 1.4".)

public class Example {
    public static void main(String[] args) {
        String enum = "hello";
    }
}

Ответ 9

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

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

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

Ответ 10

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

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

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

Ответ 11

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

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

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

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

...

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

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

Ответ 12

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

Ответ 13

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

public class Test {
    float strictfp = 3.1415f;
}

Ответ 14

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