2012-05-09 24 views
7

Me hicieron un examen de ayer en Java. Hay algo que me parece realmente ambiguo.Acceso al método estático al constructor no estático?

reglas son simples:

  1. método estática puede no no puede llamar a los métodos no estáticos.
  2. constructores son una especie de método sin ningún tipo de retorno.

    public class Main { 
        public static void main(String[] args) { 
         Main p = new Main(); 
         k(); 
        } 
    
        protected Main() { 
         System.out.print("1234"); 
        } 
    
        protected void k() { 
        } 
    } 
    
    Main p = new Main() line prints 1234 
    k() line raises error 
    

Entonces, ¿por qué sucedió esto? ¿No entra en conflicto con las reglas de Java anteriores?

+3

Si fue imposible llamar a un constructor desde un método estático, entonces no pudo construir ningún objeto nunca. –

Respuesta

10

1 - El método estático no puede llamar a métodos no estáticos.

Claro que pueden, pero necesitan un objeto para llamar al método de.

En un método estático, no hay referencia this disponible, por lo que foo() (que es equivalente a this.foo()) es ilegal.

2 - Los constructores son un tipo de método sin tipo de devolución.

si deben ser compared to methods, diría constructores están más cerca de los métodos no estáticos (ya que no es de hecho una referencia this dentro de un constructor).

Teniendo en cuenta este punto de vista, debe quedar claro a usted por qué un método estático puede llamar a un constructor sin ningún problema.


lo tanto, para resumir:

Main p = new Main(); 

está bien, ya que new Main() no depende de ningún objeto existente.

k(); 

no es bueno, ya que es equivalente a this.k() y this no está disponible en su método main (estática).

+0

Lo que confunde a las personas todo el tiempo es el hecho de que 'new main()' NO es una simple llamada de constructor: es la aplicación del operador unario 'new' al tiempo que especifica qué constructor llamar ** como parte de un una asignación más amplia + procedimiento de inicialización **. –

+0

@MarkoTopolnik, JLS reference? – aioobe

+0

¿Realmente lo necesita, ya que es obvio? Al aplicar 'new' ** se asigna memoria desde el montón ** - eso no está escrito en el constructor, por ejemplo.También llama a ** todos los inicializadores de instancias **, otro hecho seguramente obvio para usted. Eso tampoco está escrito en ningún lugar del código de constructor. También llama al constructor con 'this' repentinamente definido, no por el que llama, sino por un código implícito. Constructor no es más que una devolución de llamada, en realidad. –

4

No. constructores no son métodos ordinarios en este respecto. El objetivo del constructor es, bueno, construir una nueva instancia de la clase.

Por lo tanto, se puede invocar en su alcance estática también. Sólo pensar en ello: si necesitaba una instancia existente de su clase con el fin de crear una nueva instancia de la misma, sólo tendría que nunca sería capaz de crear una instancia que nunca.

algunas aclaraciones:

método estática puede no no puede llamar a los métodos no estáticos.

No del todo. Puede llamar a un método no estático desde un método estático, solo necesita alcance a un objeto específico de esa clase. Es decir.

p.k(); 

funcionaría perfectamente en la muestra del código anterior.

La llamada

k(); 

estaría bien dentro de un método de instancia (no estático). Y sería equivalente a

this.k(); 

El implícita this se refiere a la instancia actual de la clase. Siempre que el compilador vea una llamada no calificada como k() dentro de un método de instancia, automáticamente lo alineará con this.. Sin embargo, dado que los métodos estáticos no están vinculados a ninguna instancia de la clase, usted (y el compilador) no pueden hacer referencia a this dentro de un método estático. Por lo tanto, debe nombrar explícitamente una instancia de la clase para llamar a un método de instancia.

5

reglas son simples:
1 - Método estático no puede no puede llamar a los métodos no estáticos.

Eso simplemente no es verdad. Un método estático puede llamar a un método no estático, solo a través de una referencia de "destino". Por ejemplo, esto está muy bien en un método estático:

Integer x = Integer.valueOf(10); 
int y = x.intValue(); // Instance method! 

El verdadero punto dees "no hay this referencia dentro de un método estático".

2 - Los constructores son un tipo de método sin tipo de devolución.

No es un modelo realmente útil, para ser sincero. Hace más sentido (desde el punto de vista del llamador) considerar un constructor como un método estático con un tipo de retorno que es el mismo que la clase declarante, pero incluso ese no es un modelo perfecto de ninguna manera.

Le sugiero que piense en un constructor como un tipo diferente de miembro. Acepta las diferencias entre los constructores y los métodos, en lugar de tratar de ocultarlos.

+0

¿Qué piensas al comparar el constructor con una devolución de llamada que devuelve el vacío que se llama como parte de la inicialización de objetos? Ese nivel de indirección es una cosa que, en mi opinión, se escapa de las personas y causa suposiciones erróneas. –

+0

@MarkoTopolnik: depende de si lo está pensando desde el punto de vista del * que llama * (en cuyo caso "void-returning" no tiene sentido, ya que puede usar el resultado) o la * implementación * (en qué caso tiene sentido). Prefiero pensar que es algo propio, en lugar de tratar de hacer analogías tortuosas con los métodos. –

+0

No es una tontería si se tiene en cuenta que la persona que llama simplemente está aplicando 'new' y no está llamando a ninguna función. De hecho, ese es mi punto principal: uno debe respetar 'nuevo', no mirar a través de él. El valor de retorno de ese operador es la referencia, y el constructor todavía se puede ver como una devolución de llamada '' vacía ''. Estoy de acuerdo en que las analogías solo pueden ir tan lejos, pero aún así ayudan a aprender algo nuevo. –

Cuestiones relacionadas