java - ¿Es ''T.super'' una expresión legal según JLS?
eclipse java-8 (4)
Considere el siguiente conjunto de expresiones:
class T {{
/*1*/ Object o = T.super; // error: ''.'' expected
/*2*/ o.toString();
}}
Un intento de compilar esto fallará en la línea /*1*/
con el error:
error: ''.'' expected
o = T.super;
^
ambos al usar OpenJDK 1.8.0 (Ubuntu) u Oracle JDK 1.8 (Windows) .
Sin embargo, Eclipse 4.5.0 (Mars) compila esto sin ningún error y resulta en:
class T {
T();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8] // super()
4 aload_0 [this]
5 astore_1 [o] // o = T.super
7 invokevirtual java.lang.Object.toString() : java.lang.String [10]
10 pop // ^-- o.toString()
11 return
}
A partir de esto, puede ver que la línea /*1*/
del código java (línea 5
del resultado) almacena correctamente this
casted como Object
(comprensión de Eclipse de T.super
) en la variable local o
. Cuando se ejecuta el código, se completa normalmente y la línea /*2*/
produce un resultado correcto.
Hasta ahora no he encontrado nada relevante para o = T.super;
en la Especificación del lenguaje Java 8 , es decir, si es legal o no. Como no dice explícitamente que es una expresión legal, supongo que significa que es ilegal . Pero entonces, ¿por qué Eclipse lo considera legal? De ahí mi pregunta:
¿Es T.super
una expresión legal según JLS?
Editar: simplificó el código eliminando una clase interna de envoltura. Aceptar esta sintaxis fue un error de larga data en Eclipse , que se ha corregido para el hito 5 hacia Eclipse 4.6.
Esto es correcto según JLS. Especificación JLS "El formulario super.Identifier se refiere al campo denominado Identificador del objeto actual, pero con el objeto actual visto como una instancia de la superclase de la clase actual."
Basado en este super es la instancia de la superclase.
También JLS afirma que "es un error en tiempo de compilación si la clase actual no es una clase interna de la clase T o T en sí".
En tu caso, es claramente una clase interna. Puedes encontrar la versión de Java utilizada en Eclipse.
No, no es. Consulte el Capítulo 19 . La búsqueda de la palabra clave super
produce los siguientes constructos:
- límites de comodín:
extends T
/super T
; - invocación explícita del constructor:
super(args)
; - acceso de campo:
[Typename.]super.field
; - invocación al método:
[Typename.]super.method()
; - método de referencia:
super::method
.
El hecho de que compila puede considerarse un error o una extensión de idioma, aunque no hay una diferencia real entre los dos.
T.super
no es una expresión legal porque no tiene sentido. La sintaxis super
(con o sin tipo explícito) solo se usa para llamar a métodos de la superclase. T.super
no llama a ningún método (si fuera sintaxis legal), solo hace referencia a una instancia de clase. En tu caso, hace referencia a la instancia T
externa . La sintaxis correcta sería T.this
, que apuntaría a this
externo .
La definición de su clase se puede ver así (con una clase interna con nombre):
class Outer
{
// Constructor Body
{
class Inner
{{
/*1*/ Outer o = Outer.super; // error: ''.'' expected
/*2*/ o.toString();
}};
new Inner();
}
}
La forma correcta de referenciar la clase externa sería
Outer o = Outer.this; // valid