Ответ 1
Примечания по совместимости для различных версий:
Первым крупным икопом, который я помню, было введение assert
в Java 1.4. Это повлияло на много кода JUnit.
Были ли несовместимы между версиями Java, где исходный код Java/файлы классов Java, предназначенные для Java версии X, не будут компилироваться/выполняться в версии Y (где Y > X)?
В разделе "Java release" я подразумеваю такие версии, как:
Правила дома:
Примечания по совместимости для различных версий:
Первым крупным икопом, который я помню, было введение assert
в Java 1.4. Это повлияло на много кода JUnit.
Прежде всего, Sun фактически рассматривает все выпущенные вами выпуски (за исключением, конечно, 1.0), для небольших выпусков, а не для крупных.
Я не знаю ни одного примера бинарной несовместимости за это время. Однако были некоторые примеры исходной несовместимости:
В Java 5 "enum" стало зарезервированным словом; это было не раньше. Поэтому были исходные файлы, которые использовали enum в качестве идентификатора, который будет компилироваться в java 1.4, который не будет компилироваться в java 5.0. Однако вы можете скомпилировать с -source 1.4, чтобы обойти это.
Добавление методов к интерфейсу также может нарушить совместимость с исходным кодом. Если вы реализуете интерфейс и затем пытаетесь скомпилировать эту реализацию с помощью JDK, который добавляет новые методы в интерфейс, исходный файл больше не будет компилироваться успешно, поскольку он не реализует всех членов интерфейса. Это часто случается с java.sql.Statement и другими интерфейсами jdbc. Скомпилированные формы этих "недопустимых" реализаций будут работать, если вы фактически не назовете один из методов, которых не существует; если вы это сделаете, будет выведено исключение MissingMethodException.
Вот несколько примеров, которые я могу вспомнить от головы, могут быть и другие.
Интерфейс java.sql.Connection
был расширен с Java 1.5 до Java 1.6, что делает компиляцию всех классов, которые реализовали этот интерфейс.
Каждый выпуск 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.
Основной, о котором я могу думать, это введение новых зарезервированных слов:
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 выбрасывает a NumberFormatException
.
Перекомпиляторы не нужны, но рабочий код перестает работать, если он полагается на поведение 1.3.
Семантика модели памяти изменилась с 1.4 до 1.5. Он был изменен так, чтобы, помимо других вещей, снова была дважды проверена блокировка. (Я думаю, что волатильная семантика была исправлена.) Это было нарушено.
Следующее будет скомпилировано в 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";
}
}
Очевидно, что соглашение об именах имена выпусков не обратное - совместимый.
Еще один пример совместимости с 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
", фактическая реализация говорит иначе. Я предполагаю, что это ошибка документации.
См. отчет об изменениях API для библиотеки классов JRE: http://abi-laboratory.pro/java/tracker/timeline/jre/
Отчет включает в себя анализ двоичной и исходной совместимости классов Java.
Отчет создается инструментом japi-compliance-checker.
...
Еще один интересный анализ JDK 1.0-1.6 можно найти на странице Japitools JDK-Results.
Как сказал Шон Рейли, новый метод может нарушить ваш код. Помимо простого случая, когда вы должны реализовать новый метод (это вызовет предупреждение компилятора), существует худший случай: новый метод в интерфейсе имеет ту же подпись, что и у вас уже есть в вашем классе. Единственный намек компилятора - предупреждение о том, что аннотация @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.