2011-02-13 27 views
9

¿Por qué el siguiente código imprime "Principal"?Herencia en métodos estáticos

public class Main 
{ 
    public static void method() 
    { 
     System.out.println("Main"); 
    } 

    public static void main(String[] args) 
    { 
     Main m = new SubMain(); 
     m.method(); 
    } 
} 

class SubMain extends Main 
{ 
    public static void method() 
    { 
     System.out.println("SubMain"); 
    } 
} 

En tiempo de ejecución, m está apuntando a una instancia de Submain, por lo que debe imprimir conceptualmente "subprincipal".

+3

Incluso puede escribir 'Main m = null;' y luego llamar al método, la expresión antes de que el punto no se utilice en absoluto. –

Respuesta

18

Los métodos estáticos se resuelven en el tipo de tiempo de compilación de la variable. m es del tipo Main, por lo que se llama al método en Main.

Si lo cambia a SubMain m ..., se llamará al método SubMain.

+13

Además de esta respuesta, le recomiendo que no llame a métodos estáticos desde un objeto instancia y los llame desde el nombre de clase (por ejemplo: SubMain.method() en lugar de m.method()). – andrewjs

+0

Esta es la razón por la que java lo advierte cuando intenta invocar un método estático en un objeto instancia. –

+0

@EricFitting Java no te advierte, pero tu ide puede advertirte. –

2

Eclipse me da este tipo de advertencia cuando trato de hacer este tipo de cosas:

El XXX método estático() del tipo XXX se debe tener acceso de manera estática

Los métodos estáticos no toman parte en la herencia. La variable es del tipo Main, por lo que el compilador resolvió su llamada de función al Main.method().

Para mayor diversión, intente configurar m en null.

15

Es porque los métodos estáticos no son polimórficos. Además, el método estático debe invocarse no por objeto sino por la clase, es decir, Main.method() o SubMain.method(). Cuando llama al m.method() java realmente llama a Main.method() porque m es del tipo Main.

Si quiere disfrutar del polimorfismo, no use métodos estáticos.

1

Java realiza el enlace anticipado para métodos estáticos, a diferencia de los métodos de instancia que están vinculados dinámicamente.

Como su variable de objeto es de tipo Principal, la llamada está vinculada a la implementación de la superclase en tiempo de compilación.

Una buena explicación está disponible here.

0

los métodos estáticos están enlazados estáticamente con su nombre de clase porque m es el tipo de clase principal y luego de la compilación se vería como siguiente Main.method(); después de la compilación de la clase ejecute el siguiente comando javap -c principal u puede ver el código de montaje JVM para la clase principal yu vería siguiente m.method // invocar estática invocan estática, invocar especial dice que estática vinculante invoke special, invoke interface dice que dynamic binding