java - sirve - jstl ejemplos
Método genérico tipo de referencia que especifica antes/después:: operador (3)
En primer lugar, se denomina testigo de tipo ( en el Tutorial oficial de Oracle ) o TypeArguments (en la Sec. 15.12 de JLS ) y está ayudando al compilador de manera efectiva con tales construcciones.
Un ejemplo:
private static void test(Callable<Object> call) {
}
private static void test(Runnable run) {
}
static class Gen<T> {
}
Y llámalo por test(Gen::new);
(esto fallará, no importa por qué), pero el punto es que agrega un testigo de tipo para ayudar al compilador, así que esto funcionaría
test(Gen<String>::new);
Entonces, cuando escribe la List<String>
, ha agregado un testigo de tipo para el tipo de destino - List
que es; en el segundo caso, está agregando uno para el método que contains
, pero no es genérico, por lo que se ignora.
¿Cuál es la diferencia entre las siguientes referencias de métodos,
BiPredicate<List<String>,String> contains1 = List<String>::contains;
BiPredicate<List<String>,String> contains2 = List::<String>contains;
BiPredicate<List<String>,String> contains3 = List<String>::<String>contains;
¿Los casos tienen nombres especiales? ¿Hay algún ejemplo similar al uso?
En:
BiPredicate<List<String>, String> contains2 = List::<String>contains;
<String>
es un argumento de tipo para una lista no genérica. List.contains
método 1 .
Mientras en:
BiPredicate<List<String>, String> contains1 = List<String>::contains;
<String>
es un argumento de tipo para una List
.
1 - En este caso particular, un argumento de tipo se ignora de acuerdo con JLS §15.12.2.1 :
Un método no genérico puede ser potencialmente aplicable a una invocación que proporciona argumentos de tipo explícito. En tal caso, los argumentos de tipo simplemente serán ignorados.
Esto es lo que Intellij me cuenta sobre ellos:
BiPredicate<List<String>, String> contains1 = List<String>::contains;
Se pueden inferir argumentos de tipo explícito
BiPredicate<List<String>, String> contains2 = List::<String>contains;
Los argumentos de tipo son redundantes para la referencia de método no genérica
Si tuvieras que dividirlas en sus respectivas funciones lambda, creo que verías lo siguiente:
BiPredicate<List<String>, String> contains1 = (List<String> strings, String o) -> strings.contains(o);
BiPredicate<List<String>, String> contains2 = (strings, o) -> strings.<String>contains(o);
Como sabemos, las (List<String> strings, String o)
se pueden reemplazar por (strings, o)
y <String>
en la segunda línea es innecesaria (ya que String#contains
no es genérica), por lo que es seguro asumir que Ambas referencias de método son equivalentes.