Я заметил разницу в поведении автоматической распаковки между Java SE 6 и Java SE 7. Мне интересно, почему это так, потому что я не могу найти никакой документации об изменениях в этом поведении между этими двумя версиями.
Вот простой пример:
Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Это прекрасно компилируется с javac из Java SE 7. Однако, если я передам компилятору аргумент «-source 1.6», я получу ошибку в последней строке:
inconvertible types
found : java.lang.Object
required: int
Я попытался загрузить Java SE 6 для компиляции с помощью собственного компилятора версии 6 (без параметра -source). Согласен и выдает ту же ошибку, что и выше.
Так что же дает? Из еще нескольких экспериментов кажется, что распаковка в Java 6 может распаковывать только значения, которые явно (во время компиляции) относятся к упакованному типу. Например, это работает в обеих версиях:
Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Таким образом, кажется, что между Java 6 и 7 функция распаковки была улучшена, так что она могла приводить и распаковывать типы объектов одним махом, не зная (во время компиляции), что значение имеет правильный упакованный тип. Однако, читая Спецификацию языка Java или сообщения в блогах, которые были написаны во время выхода Java 7, я не вижу никаких изменений в этой вещи, поэтому мне интересно, что это за изменение и как называется эта «функция» ?
Просто любопытство: из-за изменения возможно запускать "неправильные" распаковки:
Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];
Это хорошо компилируется, но дает исключение ClassCastException во время выполнения.
Любая ссылка на это?
Integer obj = new Integer(2); int x = (int)obj;
: работает на Java 7, выдает ошибку на Java 6.Ответы:
Похоже, что язык в разделе 5.5 Приведение преобразования Java 7 JLS был обновлен по сравнению с тем же разделом в Java 5/6 JLS , вероятно, для уточнения разрешенных преобразований.
Java 7 JLS говорит
Java 5/6:
Java 7 JLS также содержит таблицу (таблица 5.1) разрешенных преобразований (эта таблица не включена в Java 5/6 JLS) из ссылочных типов в примитивы. Это явно перечисляет приведение от Object к примитивам как преобразование сужающей ссылки с распаковкой.
Причина объясняется в этом электронном письме :
источник
Ты прав; проще говоря:
Это работает в Java 7, но дает ошибку компиляции в Java 6 и ниже. Как ни странно, эта функция не задокументирована; например, об этом здесь не упоминается . Спорный вопрос, новая ли это функция или исправление ошибки (или новая ошибка?), См. Некоторую связанную информацию и обсуждение . Консенсус, похоже, указывает на двусмысленность в исходной спецификации, что привело к несколько неправильной / непоследовательной реализации на Java 5/6, которая была исправлена в версии 7, потому что это было критически важно для реализации JSR 292 (динамически типизированные языки).
У автобокса Java теперь есть еще несколько ловушек и сюрпризов. Например
будет компилироваться, но не удастся (с
ClassCastException
) во время выполнения. Вместо этого будет работать:long x = (long)(int)obj;
источник