Я обновил Eclipse Photon 4.8 (http://download.eclipse.org/eclipse/downloads/drops4/S-4.9M2-201808012000/) для поддержки JDK 11 (https://marketplace.eclipse.org/content/java-11-support-eclipse-photon-49). Вроде нормально работает (Версия: 4.9)
Идентификатор сборки: I20180801-2000).
В JDK 11 есть новое переопределение метода toArray()
в Java.util.Collection:
default <T> T[] toArray(IntFunction<T[]> generator) {
return toArray(generator.apply(0));
}
Это метод по умолчанию, но он не переопределяется. Все, что он делает, это передает значение, возвращаемое предоставленной функцией генератора (используя жестко закодированный аргумент, равный нулю), в другое переопределение toArray()
, которое затем возвращает содержимое коллекции в виде массива.
Как описано в Javadoc для этого метода, его можно назвать так:
String[] y = x.toArray(String[]::new);
Это прекрасно работает, и возвращается массив String соответствующей длины, соответствующей Collection<String>
.
Javadoc также утверждает, что « реализация по умолчанию вызывает функцию генератора с нулем, а затем передает полученный массив в toArray (T []) ».
Если я предоставляю свою собственную функцию генератора, она вызывается (как показано на выходе консоли println()
), но возвращаемое значение ее метода apply()
, похоже, игнорируется. Это как если бы я вызывал toArray(String[]::new)
независимо от содержимого массива, возвращенного моей функцией генератора.
Вот MCVE:
package pkg;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.IntFunction;
public class App {
public static void main(String[] args) {
IntFunction<String[]> intFunc = (int sz) -> {
System.out.println("intFunc: sz: " + sz);
if (sz == 0) {
sz = 3;
}
String[] array = new String[sz];
for (int i = 0; i < sz; i++) {
array[i] = Character.toString('A' + i);
}
System.out.println("intFunc: array to be returned: " + Arrays.toString(array));
return array;
};
Collection<String> coll = List.of("This", "is", "a", "list", "of", "strings");
// Correctly returns the collection as an array, as described in JDK11 Javadoc.
String[] array1 = coll.toArray(String[]::new);
System.out.println("array1: " + Arrays.toString(array1) + '\n');
// Use generator function to return a different collection as an array - doesn't work.
String[] array2 = coll.toArray(intFunc);
System.out.println("array2: " + Arrays.toString(array2) + '\n');
// Use generator function to return a different collection as an array - doesn't work.
String[] array3 = coll.toArray(intFunc.apply(coll.size()-2));
System.out.println("array3: " + Arrays.toString(array3));
}
}
Вот вывод консоли, полученный при запуске MCVE:
array1: [Это список строк, из которых] a
intFunc: sz: 0
intFunc: возвращаемый массив: [A, B, C]
array2: [Это список строк, из которых] a
intFunc: sz: 4
intFunc: возвращаемый массив: [A, B, C, D]
array3: [Это список строк, из которых] a
Вывод показывает, что не имеет значения, что делает моя функция генератора - возвращаемый массив не используется.
Мой вопрос: как мне заставить эту новую реализацию toArray()
использовать массив, возвращенный моей функцией генератора, или я пытаюсь сделать что-то невозможное?
Обновление на основе комментариев и ответа от Николая:
Проблема с моим примером кода была не с генератором, а с моими тестовыми примерами. Они оказались причиной того, что генератор вернул массив с меньшим количеством элементов, чем в коллекции, поэтому вместо него был выделен новый массив, в котором будет точно храниться количество элементов в коллекции.
Тестовый пример, который возвращает массив больше, чем коллекция, работает, как ожидалось. Например этот код:
String[] array4 = coll.toArray(intFunc.apply(coll.size() + 3));
System.out.println("array4: " + Arrays.toString(array4));
дает следующий вывод консоли:
intFunc: sz: 9
intFunc: возвращаемый массив: [A, B, C, D, E, F, G, H, I]
array4: [Это список строк, null, H, I]
Вопрос SO Коллекции emptyList / singleton / singletonList / List / Set toArray объясняет, почему в возвращаемом массиве есть нулевое значение.