Votre question est justifiée. En bref, la méthode de référence n'est, en effet, utiliser le raw type (ou devrait utiliser le raw type) et de la raison, le pourquoi de la création du générique de tableaux est interdit, s'applique encore lors de l'utilisation de la méthode des références, par conséquent, être en mesure d'en silence créer une fonction de création d'un générique de la matrice est clairement en contradiction avec l'intention de la conception de langage.
La raison pour laquelle la création du générique de la matrice est interdit, c'est que le type du tableau de l'héritage, à partir d'une pré-Génériques de l'époque, est incompatible avec le type générique du système. I. e. vous pouvez écrire:
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
À cet endroit, il convient de souligner que, contrairement à certaines réponses ici, le compilateur ne pas effectuer l'inférence de type sur l'expression List[]::new
de déduire l'élément générique de type List<String>
. Il est facile de prouver que le générique de la création de la matrice est toujours interdit:
IntFunction<List<String>[]> af = List<String>[]::new; // does not compile
Depuis List<String>[]::new
est illégale, il serait étrange si List[]::new
a été acceptée sans un avertissement, en supposant qu'il soit effectivement illégale List<String>[]::new
.
JLS §15.13 stipule clairement:
Si une méthode de référence l'expression est de la forme ArrayType ::
new
, alors ArrayType doit désigner un type qui est reifiable (§4.7), ou une erreur de compilation se produit.
Cela implique déjà qu' List<String>[]::new
est illégal, car List<String>
n'est pas reifiable, alors qu' List<?>[]::new
est légal, List<?>
est reifiable, et List[]::new
est légal si l'on considère List
pour une crue de type, comme la crue de type List
est reifiable.
Ensuite, §15.13.1 états:
Si la méthode de référence l'expression est de la forme ArrayType ::
new
, un seul théorique de la méthode est considérée. La méthode a un seul paramètre de type int
, renvoie la ArrayType, et n'a pas d' throws
de la clause. Si n = 1, c'est le seul potentiellement applicables méthode; sinon, il n'y a pas potentiellement applicables méthodes.
En d'autres termes, le comportement de l' List[]::new
expression ci-dessus est le même que si vous aviez écrit:
IntFunction<List<String>[]> af = MyClass::create;
…
private static List[] create(int i) {
return new List[i];
}
sauf que la méthode de create
est uniquement théorique. Et en effet, avec cette méthode explicite de la déclaration, il y a seulement cru type de mises en garde à l' create
méthode, mais pas décoché les avertissements concernant la conversion de List[]
de List<String>[]
à la méthode de référence. Il est donc compréhensible, ce qui se passe dans le compilateur dans l' List[]::new
de cas, où la méthode à l'aide de matières types est seulement théorique, c'est à dire n'existe pas dans le code source.
Mais l'absence de décoché avertissements est une violation claire de JLS §5.1.9, Unchecked Conversion:
Laissez - G
nom générique de la déclaration de type à n paramètres de type.
Il y a un unchecked conversion les matières de la classe ou de type d'interface (§4.8) G
pour tout paramétré le type de la forme G<T₁,...,Tₙ>
.
Il y a un unchecked conversion de la crue de type array G[]ᵏ
pour tout type de tableau de la forme G<T₁,...,Tₙ>[]ᵏ
. (La notation []ᵏ
indique un type de tableau de k dimensions.)
L'utilisation d'un unchecked conversion provoque au moment de la compilation décoché avertissement , à moins que tous les arguments de type T
ᵢ (1 ≤ i ≤ n) sont sans limite de caractères génériques (§4.5.1), ou la décoché avertissement est supprimée par l' SuppressWarnings
d'annotation (§9.6.4.5).
Ainsi, une conversion de List[]
de List<?>[]
est légal, List
est paramétré avec une vive générique, mais la conversion de l' List[]
de List<String>[]
doit produire un décoché avertissement, ce qui est crucial ici, comme l'utilisation de l' List[]::new
ne produit pas de la crue de type d'avertissement qui s'affiche avec un explicite la méthode de création. L'absence de crue de type d'avertissements ne semble pas être une violation (que j'ai compris §4.8) et il ne serait pas un problème, si javac
créé les décoché avertissement.