una que privada otra objeto nombre llevan internas estaticas dentro crear clases clase anonimas java language-design

java - que - ¿Los constructores por defecto para las clases internas privadas tienen un parámetro formal?



crear un objeto de una clase dentro de otra clase (1)

Hay una diferencia entre la implementación y la especificación.

En mi opinión la declaración "excepto" de JLS

... excepto en una clase interna no privada ...

está mal redactado

Esto significa que no se requiere que el compilador declare implícitamente un parámetro formal que representa la instancia de la clase que contiene inmediatamente ... pero podría .

¿Por qué se requiere implícitamente un parámetro formal en una clase de miembro interno no privado?

Desde JLS 8.8.1 :

La clase miembro puede haber sido emitida por un compilador que es diferente al compilador de la expresión de creación de instancia de clase. Por lo tanto, debe haber una forma estándar para que el compilador de la expresión de creación pase una referencia (que represente la instancia que contiene inmediatamente) al constructor de la clase miembro

Por ejemplo, si compilo esta clase interna con un primer compilador:

package p1; public class Ctors { public class MyInner { } }

Si quiero compilar esta subclase con otro compilador:

package p2; import p1.Ctors; public class SubCtors { public SubCtors() { new Ctors(); } }

el segundo compilador debe poder usar el constructor predeterminado con el parámetro formal. En este caso, la instancia de la clase SubCtors con una instancia de SubCtors .

¿Por qué implícitamente no se requiere un parámetro formal en una clase de miembro interno no privado?

Debido a que una clase miembro no privada interna siempre es visitada por el mismo compilador que la compiló. Como se muestra, javac genera el mismo constructor independientemente de la visibilidad de la clase, pero no es obligatorio. Otra implementación del compilador es libre de elegir otra manera.

También hay otro punto en JLS 8.8.1 que está muy en la misma línea

En una expresión de creación de instancia de clase para una clase local (no en un contexto estático) o una clase anónima, §15.9.2 especifica la instancia que contiene inmediatamente la clase local / anónima. La clase local / anónima es necesariamente emitida por el mismo compilador que la expresión de creación de instancia de clase. Ese compilador puede representar la instancia inmediatamente adjunta como quiera que lo desee. No es necesario que el lenguaje de programación Java declare implícitamente un parámetro en el constructor de la clase local / anónima.

Advertencia # 1: Esto es en realidad un doble factor potencial: primero, ¿el constructor para una clase interna privada tiene un parámetro formal? Si es así, ¿por qué el JLS dice que no? Y si no, ¿cómo / por qué no?

Advertencia # 2: Esta pregunta no es para especulación. Estoy buscando respuestas autorizadas solamente.

Los constructores predeterminados se definen en JLS 8.8.9 , que establece (en parte):

El constructor predeterminado no tiene parámetros formales, excepto en una clase de miembro interno no privado , donde el constructor predeterminado declara implícitamente un parámetro formal que representa la instancia de la clase que contiene inmediatamente (§8.8.1, §15.9.2, §15.9.3 ).

(énfasis añadido)

El bit "no privado" me parece extraño: para que una clase interna pueda acceder a los campos definidos en su clase adjunta, necesita una referencia a esa instancia. Esto debería ser igual sin importar si la clase interna es privada.

De hecho, javac parece estar de acuerdo conmigo, en contradicción con la especificación. Si compilo esto:

public class Ctors { private class MyInner { } }

... y ejecute javap -c -private , luego vemos un constructor con un solo parámetro formal, para la instancia de la clase envolvente:

$ javap -c -private Ctors/$MyInner Compiled from "Ctors.java" class Ctors$MyInner { final Ctors this$0; private Ctors$MyInner(Ctors); Code: 0: aload_0 1: aload_1 2: putfield #1 // Field this$0:LCtors; 5: aload_0 6: invokespecial #2 // Method java/lang/Object."<init>":()V 9: return }

Para referencia, esto está en Oracle JDK 1.8.0_05.

Así que JLS dice que el constructor predeterminado para las clases privadas de miembros internos no tiene parámetros formales, pero javac / javap dicen que tiene uno. (Mi comprensión de la forma más natural en que funcionan las cosas también diría que debería tener una, por lo poco que vale la pena). ¿Cuál es el correcto y por qué el JLS excluye específicamente las clases internas privadas?