Ответ 1
Ваш вопрос оправдан. Короче говоря, ссылка на метод действительно использует исходный тип (или должен использовать необработанный тип), и причина, почему создание общих массивов запрещена, по-прежнему применяется при использовании ссылок на методы, следовательно, возможность тихо создавать функцию, создающую общий массив явно нарушает намерение дизайна языка.
Причина, по которой создание универсального массива запрещена, заключается в том, что наследование типа массива, связанное с эрой до Generics, несовместимо с системой типа generic. То есть вы можете написать:
IntFunction<List<String>[]> af = List[]::new; // should generate warning
List<String>[] array = af.apply(10);
Object[] objArray = array;
objArray[0] = Arrays.asList(42);
List<String> list = array[0]; // heap pollution
В этом месте следует подчеркнуть, что в отличие от некоторых ответов здесь компилятор не выполняет вывод типа в выражении List[]::new
, чтобы вывести общий тип элемента List<String>
. Его легко доказать, что создание общего массива все еще запрещено:
IntFunction<List<String>[]> af = List<String>[]::new; // does not compile
Так как List<String>[]::new
является незаконным, было бы странно, если бы List[]::new
был принят без предупреждения, выведя его как эффективный незаконный List<String>[]::new
.
JLS §15.13 четко заявляет:
Если ссылочное выражение метода имеет форму ArrayType
::
new
, тогда ArrayType должен обозначать тип, который можно повторно идентифицировать (§4.7), или возникает ошибка времени компиляции.
Это уже означает, что List<String>[]::new
является незаконным, поскольку List<String>
не может быть повторно идентифицируемым, тогда как List<?>[]::new
является законным, поскольку List<?>
является допустимым, а List[]::new
является законным, если мы рассматриваем List
как raw type, так как сырой тип List
можно отменить.
Тогда в §15.13.1 говорится:
Если ссылочное выражение метода имеет форму ArrayType
::
new
, рассматривается один условный метод. Метод имеет единственный параметр типаint
, возвращает ArrayType и не имеет предложенияthrows
. Если n = 1, это единственный потенциально применимый метод; в противном случае не существует потенциально применимых методов.
Другими словами, поведение выражения List[]::new
выше такое же, как если бы вы написали:
IntFunction<List<String>[]> af = MyClass::create;
…
private static List[] create(int i) {
return new List[i];
}
за исключением того, что метод create
является только условным. И действительно, с этим явным объявлением метода в методе create
есть только предупреждения типа типа, но не отмечены предупреждения о преобразовании List[]
в List<String>[]
по ссылке метода. Поэтому понятно, что происходит в компиляторе в случае List[]::new
, где метод с использованием типов raw является только условным, т.е. Не существует в исходном коде.
Но отсутствие непроверенных предупреждений является явным нарушением JLS §5.1.9, Unchecked Conversion:
Пусть
G
укажите объявление общего типа с параметрами типа n.Существует непроверенное преобразование из исходного класса или типа интерфейса (§4.8)
G
в любой параметризованный тип формыG<T₁,...,Tₙ>
.Существует непроверенное преобразование из типа необработанного массива
G[]ᵏ
в любой тип массива формыG<T₁,...,Tₙ>[]ᵏ
. (Обозначение[]ᵏ
указывает тип массива k размерностей.)Использование непроверенного преобразования вызывает предупреждение без компиляции, если все аргументы типа
T
ᵢ (1 ≤ я ≤ n) не являются неограниченными подстановочными знаками (§4.5.1), или непроверенное предупреждение подавляетсяSuppressWarnings
аннотации (§9.6.4.5).
Итак, преобразование List[]
в List<?>[]
является законным, поскольку List
параметризуется неограниченным подстановочным знаком, но преобразование с List[]
в List<String>[]
должно приводить к неконтролируемому предупреждению, что имеет решающее значение здесь, так как использование List[]::new
не создает предупреждение типа raw, которое появляется с явным методом создания. Отсутствие необработанных предупреждений типа не является нарушением (насколько я понял §4.8), и это не было бы проблемой, если javac
создало требуемое непроверенное предупреждение.