Java静态方法(类方法)的继承

Java静态方法、静态变量是可以被继承的

背景:最近因为个人工作的原因,转战到Java领域。在学习过程中发现,网上有关Java静态继承,都说不能继承,且子类静态方法重写说成是隐藏了父类方法云云的。

下面我来挑战一下,如果不对请高手指正;如果对了希望对静态继承困惑的程序员有所帮助

1.类与对象的关系,先来张图压压惊
Java静态方法(类方法)的继承
这里先来说明一下
· Sub、Father为Java类结构的底层实现,Sub继承Father通过super指针实现
· obj为Sub实例化的对象,其中fatherObj由Sub构造器底层实现,或构造器中调用super方法实现

2.方法的调用链
举个例子
Java code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Father {
    public void a_method {
        System.out.println("我正在调用父类方法");
    }
}
 
public class Sub extends Father {
}
 
public class Test {
    public static void main(String [] args) {
        Sub obj = new Sub();
        obj.a_method();
    
}

调用过程如下
· 实例化obj
· 调用obj的a_method方法:由于方法都定义在类中,当obj调用方法时将通过kind_class指针找到其对应的类,并在类的methods数组中查找a_method方法
· Sub中因为未定义a_method方法,因此通过super指针在其父类Father中的methods种查找
· 最终a_method方法被调用

3.静态方法的调用链
终于说到静态方法了,不容易啊,接着上个例子
Java code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Father {
    public static void two_method {
        System.out.println("父类静态方法2");
    }
 
    public static void three_method {
        System.out.println("父类静态方法3");
    }
}
 
public class Sub extends Father {
    public static void three_method {
        System.out.println("子类静态方法3");
    }
}
 
public class Test {
    public static void main(String [] args) {
        Sub.two_method();  //正规的静态方法(类方法)调用规范
 
        Sub obj = new Sub();
        obj.two_method();  //不正规的静态方法(类方法)调用规范,Java不会报错,在一些语言中会报错
    
}

针对Sub.two_method的调用方式
· 通过Sub类中的static_methods数组查找two_method
· Sub类不包含该方法,因此通过super指针在其父类的static_methods中查找
· 最终Father类中的two_method方法被调用

针对obj.two_method的调用方式
· 查看obj变量声明的类型(与实际的obj对象半毛钱关系都没有),这里是Sub类型(后面会说用Father引用的区别)
· 通过Sub.two_method()实现调用(见上述)

4.针对很多帖子说静态方法不能被继承的解释
最后一个例子了,Sub与Father类的定义如上,此处仅Test类
Java code
1
2
3
4
5
6
7
8
9
public class Test {
    public static void main(String [] args) {
        Sub obj = new Sub();
        Father father = new Sub();
         
        obj.three_method();      //输出结果:实际调用了Sub中定义的方法
        father.three_method();  //输出结果:实际调用了Father中定义的方法
    
}

解释:上述同一对象产生不同结果,网上很多帖子都以此为例,阐述静态方法不能继承。
实际上,这里有两个误区:第一,用对象调用静态方法是一种非规范方式,第二,所谓的继承本质上使通过一系列调用链实现的