¿Por qué no se compila “array instanceof Iterable” en Java?
arrays compiler-errors (4)
Object[] array = new Object[]{};
System.out.println((array instanceof Serializable));//passed
System.out.println((array instanceof Cloneable));//passed
Este código compila y ejecuta. La salida es:
true
true
Sin embargo, este código no compila:
System.out.println((array instanceof Iterable));//not passed
El compilador de Eclipse reporta:
Tipos de operandos condicionales incompatibles Objeto [] e Iterable
Descubrí que las matrices solo se pueden comparar entre la interfaz Serializable
y Cloneable
cuando se utiliza la operación instanceof
. ¿Alguien puede decirme por qué?
De acuerdo con la edición JLS, Java SE 7 , § 15.20.2 ( instanceof
operador de comparación de tipos):
Si una conversión de la expresión relacional al tipo de referencia se rechazara como un error en tiempo de compilación, entonces la
instanceof
expresión relacional también produce un error en tiempo de compilación. En tal situación, el resultado de lainstanceof
expresión nunca podría ser cierto.
Y § 15.16 (Expresiones de reparto) establece:
Es un error de tiempo de compilación si el tipo de tiempo de compilación del operando nunca se puede convertir al tipo especificado por el operador de conversión según las reglas de conversión de conversión (§ 5.5 ).
Finalmente, el § 5.5.1 (Conversión de tipo de referencia) establece:
Dado un tipo de referencia de tiempo de compilación S (fuente) y un tipo de referencia de tiempo de compilación T (destino), existe una conversión de conversión de S a T si no se producen errores de tiempo de compilación debido a las siguientes reglas.
[...]
Si S es un tipo de matriz SC [], es decir, una matriz de componentes de tipo SC :
- Si T es un tipo de interfaz, entonces se produce un error en tiempo de compilación a menos que T sea del tipo
java.io.Serializable
o del tipoCloneable
(las únicas interfaces implementadas por arrays).
Por lo tanto, Java requiere que su prueba para ver si un tipo de matriz es una instancia de java.lang.Iterable
resulta en un error en tiempo de compilación.
Si quieres probar y hacerlo funcionar (siempre devuelve false
) de todos modos, puedes convertir la matriz a Object
primero, así:
System.out.println((((Object)array) instanceof Iterable));
Debido a que java es un lenguaje estático, el compilador sabe que una matriz no será Iterable
en el momento de la compilación, el compilador sabe que la array instanceof Iterable
nunca podría ser cierta, por lo que provoca un error en tiempo de compilación para advertirle.
Está confundiendo la idoneidad de un objeto para su uso en un bucle foreach, y la interfaz Iterable
, que los arreglos no implementan.
Tanto las matrices como Iterable son compatibles con la sintaxis de foreach.
Eso no significa que las matrices sean iterables.
Supongo que es porque tanto Serializable
como Cloneable
son interfaces de marcadores donde Iterable
no lo es.