一、java覆盖如何执行:编译看左边,运行看右边

在子类方法覆盖父类方法时,在编译期,编译器会检查这个对象的引用类型是否含有此方法。如果没有则编译会出错,有则会通过编译。但在执行期,JVM寻找的不是引用指向的类型,而是堆上的对象。(即编译看左边,运行看右边)。

1.子类方法覆盖了父类方法

//Father类
public class Father {
    
    public void turnOn(){
        System.out.println("父类方法turnOn执行");
    }
    
}
//Son类,继承了Father类
public class Son extends Father {
    
    @Override
    public void turnOn() {
        System.out.println("子类方法turnOn执行");
    }
 
}

public class Demo {
    public static void main(String[] args) {
        Father f = new Son();
        f.turnOn();
    }
}

运行Demo类中的main()方法:

在编译期,编译器会检查对象f的引用类型(即Father)是否有turnOn(),由于Father类有这个方法,于是编译器不会报错,程序编译成功。在运行期,究竟运行Father类的两个方法还是Son类的方法呢?JVM会从对象f开始向上找直到找到turnOn()为止,由于我们在Son类覆盖了turnOn(),所以JVM会执行Son类的turnOn()。

javaio流覆盖同名文件 覆盖 java_System

2.父类引用不能调用子类特有的方法

//将上面的Son.class修改成下面这个
public class Son extends Father {
    @Override
    public void turnOn() {
        System.out.println("子类方法turnOn执行");
    }

    //定义一个只有子类有父类没有的方法
    public void sonFunction(){
        System.out.println("子类独有方法");
    }
}

修改Demo的main()为下图的代码,编译,可以看到编译器找不到sonFunction()。为什么呢?因为根据覆盖的原理,f的引用类型(Father)是没有sonFunction()方法的,所以就会编译报错。

javaio流覆盖同名文件 覆盖 java_父类_02

3.父类引用调用子类特有的方法?利用instanceof或抽象类

下面只介绍instanceof,抽象类快忘光了,下次再补充...(反正应该没人看我的文章)。

将Demo的代码修改成下图:

public class Demo {
    public static void main(String[] args) {
        Father f = new Son();
        f.turnOn();
        if(f instanceof Son){
        //对象A instanceof B,如果对象A是类B的对象,则返回true,否则返回false
            Son s = (Son) f;//向下转型,将f由Father类的引用转为Son类的引用
            s.sonFunction();//调用Son类独有的方法
        }
    }
}

javaio流覆盖同名文件 覆盖 java_javaio流覆盖同名文件_03

二、java子类方法覆盖父类方法应该遵守的规则

1、参数必须要一样,且返回类型要兼容

父类方法使用了哪种参数,覆盖此方法的子类也一定要使用相同的参数。不论父类的声明的返回类型是什么,子类必须声明返回一样的类型或该类型的子类型。

2、不能降低方法的存取权限

这代表存取权限必须相同,或者更为开放。举例来说,你不能在子类中覆盖一个公有方法并将它标记为私有。这会让JVM在编译期以为通过的是个公有方法,然后在执行期才会被JVM阻止存取。

public class Father {

    public void turnOn(){
        System.out.println("父类方法turnOn执行");
    }

}
public class Son extends Father {
    @Override
    private void turnOn() {//此处报错!!!!报错信息如下图
        System.out.println("子类方法turnOn执行");
    }

}

javaio流覆盖同名文件 覆盖 java_System_04