2010-09-10 14 views
32

¿Alguien sabe por qué puede hacer referencia a un método static en la primera línea del constructor usando this() o super(), pero no es un método no estático?¿Por qué no puedo hacer referencia a un método de instancia mientras invoco explícitamente un constructor?

Considérese el siguiente trabajo:

public class TestWorking{ 
    private A a = null; 
    public TestWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestWorking(B bParam) 
    { 
     this(TestWorking.getAFromB(bParam)); 
    } 

    //It works because its marked static. 
    private static A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 

Y el siguiente ejemplo no laborable:

public class TestNotWorking{ 
    private A a = null; 
    public TestNotWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestNotWorking(B bParam) 
    { 
     this(this.getAFromB(bParam)); 
    } 

    //This does not work. WHY??? 
    private A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 
+1

Podría ser solo el código de muestra, pero una preocupación que tendría sobre este código es que tienes lógica para construir una instancia 'A' de una instancia' B' enterrada en una tercera clase 'TestNotWorking'. –

+0

Estoy de acuerdo con su preocupación. La razón por la que lo hago así es la siguiente: estoy usando una API de terceros que tiene capacidad limitada en una clase y la clase está marcada como final.La única forma era clonar el objeto original y trabajar en la copia. Usé el objeto original como el parámetro para mi nuevo objeto. Para el propósito del ejemplo lo modifiqué un poco. – Koekiebox

+0

@Koekiebox ¿Por qué te preguntas que TestNotWorking.getAFromB (bParam) no funciona? es un método de instancia. deberías crear un objeto o usar esto. – gstackoverflow

Respuesta

16

métodos no estáticos son los métodos de instancia. Solo se puede acceder a este en la instancia existente, y la instancia aún no existe cuando estás en el constructor (todavía está en construcción).

¿Por qué es así? Debido a que los métodos de instancia pueden acceder a campos de instancia (no estáticos), que pueden tener valores diferentes en instancias diferentes, por lo que no tiene sentido llamar a dicho método en otra cosa que no sea la instancia existente y terminada.

+28

Esto está cerca, pero no es exacto. Las instancias * do * existen cuando estás en un constructor, y * puedes * invocar métodos de instancia en ellas. Pero no puedes hacerlo hasta que el constructor de la superclase se haya completado. Si desea invocarlos dentro de su propio constructor, está bien, pero la superclase debe estar terminada. – erickson

+0

Esta no es una respuesta exacta. Comenta también que no entiendo totalmente el punto porque la pregunta no es sobre llamar al super constructor sino al constructor de la misma clase, por supuesto, también es porque primero necesitamos una llamada de super constructor, pero la respuesta y el comentario no lo ponen claramente. –

+0

¿Qué pasa con este código? ** clase ClassForTest { ClassForTest (int k) { }; { método(); } ClassForTest() { esto (1); }; método int() {return 1;}} ** – gstackoverflow

1

Creo que es porque las variables de instancia final aún no están configuradas (por lo que aún no tiene ninguna instancia) y un método de instancia podría tener acceso a una. Mientras que toda la inicialización estática se ha realizado antes de la llamada al constructor.

Greetz, ghad

1

porque cuando se llame a este o super en el constructor de su objeto no está construido todavía. (su instancia aún no se ha inicializado). así que llamar a un método de instancia no hace escena.

0

Si un método no es estático, debe llamarlo a un objeto.

En el segundo ejemplo, necesitaría crear un objeto de la clase TestNotWorking y llamar al getAFromB en ese objeto.

Algo así como:

object = new TestNotWorking(); 
object.getAFromB(bParam); 
1

TestNotWorking no se ha inicializado en ese punto. El problema es que el primer constructor (TestNotWorking (A aParam)) podría llamar a super() (internamente siempre lo hace), lo que significa que llamaría a un método antes de invocar al constructor de la superclase. Eso es ilegal.

11

Ver el Java Language Specification 8.8.7.1. Esto indica que

Una declaración explícita de invocación del constructor en un cuerpo del constructor no puede referirse a cualquier variables de instancia o métodos de instancia o clases internas declarados en esta clase o cualquier superclase, o utilizar this o super en cualquier expresión; de lo contrario, se produce un error en tiempo de compilación.

Esto se debe a que no puede llamar a un método de instancia antes de que se cree la instancia. Por cierto, es posible llamar a un método de instancia más adelante en el constructor (aunque no es una solución para usted).

+0

** o usa esto o súper en cualquier expresión; de lo contrario, se produce un error en tiempo de compilación ** aclare – gstackoverflow

+0

@Marc que significa que la instancia se crea en el montón después de que se realiza la invocación explícita/implícita del constructor de la superclase, aunque su inicialización aún no se haya completado. – dannail

Cuestiones relacionadas