Почему следующее условие возвращает true с JDK 8, тогда как оно возвращает false с JDK 9?
String[].class == Arrays.asList("a", "b").toArray().getClass()
Почему следующее условие возвращает true с JDK 8, тогда как оно возвращает false с JDK 9?
String[].class == Arrays.asList("a", "b").toArray().getClass()
Тип List возвращаемый asList - Arrays$ArrayList. Метод toArray в JDK 8 для этого класса:
@Override
public Object[] toArray() {
return a.clone();
}
Но в JDK 9+ это:
@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}
В обоих случаях String[] передается asList, но в случае JDK 8 он клонируется, который сохраняет свой тип массива (String[]), а в JDK 9+ он копируется с использованием Arrays.copyOf с явным новым тип массива Object[].
Эта разница означает, что в JDK 8 Arrays.asList("a", "b").toArray().getClass() возвращает String[] а в JDK 9+ возвращает Object[], поэтому в JDK 9+ ваш выражение будет оцениваться как false.
Причиной этого изменения является JDK-6260652 с мотивировкой:
В документации Коллекции утверждается, что
collection.toArray()"идентичен по функции"
collection.toArray(new Object[0]);Однако реализация
Arrays.asListне следует этому: если он создан с массивом подтипа (например,String[]), егоtoArray()вернет массив того же типа (потому что он используетclone()) вместоObject[].Если позже кто-то попытается сохранить не-Strings (или что-то еще) в этом массиве,
ArrayStoreException.
Так что это изменение было сделано, чтобы исправить предыдущее поведение.
Если это проблема для вас, в соответствующей заметке о выпуске предлагается это в качестве обходного пути:
Если эта проблема возникает, перепишите код для использования формы с одним аргументом
toArray(T[])и предоставьте экземпляр нужного типа массива. Это также устранит необходимость в приведении.String[] array = list.toArray(new String[0]);
Я бы сказал, что это была ошибка в JDK 8, и до этого она была исправлена.
List<T>.toArray() всегда объявлялся как возвращающий Object[] (см. JavaDoc) - что в действительности он возвращал String[] в особом случае, было ошибкой.
Здесь есть несколько причин
1) Это ошибка в JDK 8, где должен возвращаться java.lang.Object но это не так, и это исправлено в JDK 9+
@Override
public Object[] toArray() {
return a.clone();
}
2) оператор == всегда используется для сравнения ссылок, поэтому java.lang.String или java.lang.Object являются объектами, которые являются одноэлементными и неизменяемыми, загружаемыми во время запуска JVM.
System.out.println(String[].class.hashCode()); //2018699554
System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554