Как использовать [TypeArguments] со ссылкой на конструктор в Java 8?
Раздел 15.13 Спецификации языка Java для Java 8 описывает эту форму синтаксиса ссылки на метод для создания ссылки на конструктор:
ClassType :: [TypeArguments] new
Например:
String s = "abc";
UnaryOperator<String> test0 = String::new; // String(String) constructor.
String s0 = test0.apply(s);
System.out.println("s0 = " + s0); // Prints "abc".
char[] chars = {'x','y','z'};
Function<char[], String> test1 = String::new; // String(char[]) constructor.
String s1 = test1.apply(chars);
System.out.println("s1 = " + s1); // Prints "xyz"
Это все работает нормально, но кажется, что абсолютно все (кроме примитивов) также может быть предоставлено для [TypeArguments], и все по-прежнему работает:
Вот глупый пример, чтобы доказать это:
Function<String, String> test2 = String::<LocalDateTime, Thread[]>new; // Compiles !!!???
String s2 = test2.apply("123");
System.out.println("s2 = " + s2); // Prints "123"
Возникает несколько вопросов:
[1] Поскольку класс String даже не использует обобщенные значения, действительно ли компилятор допускает создание этой ссылки на конструктор test2 с этими бессмысленными [TypeArguments]?
[2] Что может быть полезным примером использования [TypeArguments] при создании ссылки на конструктор?
[3] При каких условиях необходимо указывать [TypeArguments] при создании ссылки на конструктор?
1 ответ
1 15.13.1. Объявление во время компиляции ссылки на метод
Если выражение ссылки на метод имеет форму ClassType:: [TypeArguments] new, потенциально применимые методы представляют собой набор условных методов, соответствующих конструкторам ClassType....
В противном случае потенциальные методы-члены-члены являются конструкторами ClassType и обрабатываются так, как если бы они были методами с возвращаемым типом ClassType. Среди этих кандидатов выбираются методы с соответствующей доступностью, arity (n) и аргументом типа arity (производным от [TypeArguments]), как указано в §15.12.2.1.
JLS 15.12.2.1. Определить потенциально применимые методы
Этот пункт подразумевает, что неуниверсальный метод может быть потенциально применим к вызову, который предоставляет явные аргументы типа. Действительно, это может оказаться применимым. В таком случае аргументы типа будут просто игнорироваться.
2 Всякий раз, когда конструктор параметризован. Я никогда не сталкивался с одним.
public class Foo {
public <T> Foo(T parameter) {
...
Function<String, Foo> test = Foo::<String>new
3 Когда компилятор не может определить тип.