Según Java Generic y Collections de Maurice Naftalin, en las siguientes opciones:
El primero y el segundo están permitidos, pero el tercero no, que funciona bien en Java 8 (versión "1.8.0_321"). Las opciones 1 y 2 compilan y la opción 3 da un error de compilación. Pero la tercera opción funciona bien con java 17 (versión "17.0.1" 2021-10-19 LTS). ¿Podría ayudarme a entender por qué funciona en java 17. código de muestra que estoy intentando?
var a = List.of(2,3,4,5,23); var b = a instanceof List<? extends Object>; return b;Antes de Java 16, el único propósito de instanceof era verificar si un objeto al que se hace referencia se puede asignar al tipo especificado y dado que el borrado de tipo impide verificar si un objeto realmente se puede asignar a un tipo parametrizado, no tenía sentido permitir una expresión que pretendiera que tal prueba era posible.
Lo único que se podía probar era si el objeto es una instancia de List y, por lo tanto, solo se permitía escribir … instanceof List o … instanceof List<?> , ya que ninguno pretende probar el tipo de elemento de la lista.
A partir de Java 16 (disponible como versión preliminar desde el 14), instanceof permite declarar una nueva variable del tipo especificado.
Por ejemplo:
public void someMethod(Iterable<String> i) { if(i instanceof List<String> l) { if(l.isEmpty()) return; // optimized List processing } else { // generic iterable processing } }que es equivalente a
public void someMethod(Iterable<String> i) { if(i instanceof List<String>) { List<String> l = (List<String>)i; if(l.isEmpty()) return; // optimized List processing } else { // generic iterable processing } }Para la declaración de una nueva variable, no sería práctico limitarse a tipos sin formato o tipos comodín. Por lo tanto, ahora se permite especificar argumentos de tipo real, que son relevantes para la declaración y asignación de variables implícitas. Dado que el tipo de elemento aún no se puede verificar, solo se le permite especificar tipos a los que se podría convertir el tipo fuente en tiempo de compilación sin una conversión no verificada.
Entonces, lo siguiente no sería válido.
Iterable<?> i = null; boolean b = i instanceof List<String>; porque no puedes convertir con seguridad desde Iterable<?> a List<String> .
En su ejemplo, var a = List.of(2,3,4,5,23); declara a como List<Integer> , por lo tanto, a instanceof List<? extends Object> es válido porque List<Integer> se puede asignar a List<? extends Object> (incluso sin un molde).
Por supuesto, especificar tipos de elementos que no están marcados solo es útil si declara una variable como en el primer ejemplo. Pero el lenguaje Java sigue el principio de no agregar reglas adicionales solo porque alguna construcción es menos útil que la otra. Por lo tanto, ahora siempre puede especificar argumentos de tipo real para instanceof siguiendo las mismas reglas, ya sea que declare una variable o no.
Esta función se denomina Coincidencia de patrones , ya que se considera un caso especial de un concepto más amplio al que se dirige Java. En JDK 17, hay una función similar para switch disponible como vista previa.
Ver también§14.30. Patrones en la especificación del lenguaje Java.