2011-02-13 137 views
9

为什么下面的代码打印“Main”?静态方法的继承

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"); 
    } 
} 

在运行时,m指向的Submain一个实例,所以应该在概念上打印“SubMain”。

+3

你甚至可以写`Main m = null;`然后调用方法,表达式在点之前根本不用。 – 2011-02-13 23:19:58

回答

18

静态方法在变量的编译时类型上得到解决。 m类型为Main,因此调用Main中的方法。

如果将其更改为SubMain m ...,则将调用SubMain上的方法。

+13

除了这个答案,我建议你不要从实例对象中调用静态方法,并从类名(例如:SubMain.method()而不是m.method())中调用它们。 – andrewjs 2011-02-13 22:48:20

2

Eclipse中给了我这种警告,当我尝试做这样的事情:

静态方法XXX()从类型XXX应以静态方式

访问静态方法不参与继承。该变量的类型为Main,因此编译器将您的函数调用解析为Main.method()

为了增添趣味,请尝试将m设置为null

15

这是因为静态方法不是多态的。此外,静态方法不应该由对象调用,而应该使用类,即Main.method()SubMain.method()。 当您致电m.method()时,java实际上调用Main.method(),因为m的类型是Main。

如果您想享受多态,请不要使用静态方法。

1

Java执行静态方法的早期绑定,与动态绑定的实例方法不同。

因为您的对象变量是Main类型的,所以调用在编译时绑定到超类实现。

有一个很好的解释here

0

静态方法与它们的类名称是静态绑定的,因为m是Main类的类型 然后在编译后它看起来像下面的样子 Main.method(); 类的编译后 运行以下命令 的javap -c主要 ü可以看到主类 JVM的汇编代码和u会看到以下 m.method //调用静态 调用静态,调用特殊告诉静绑定 调用特殊的,调用接口告诉动态绑定