方法覆盖指的是如果在子类中定义的一个方法,其名称,返回类型及参数签名正好与父类中的某个方法的名称,返回类型及参数签名相匹配,那么就可以说子类的方法覆盖了父类的方法。


方法的覆盖必须满足多种约束,下面将一一进行介绍:

(1)子类方法的名称,返回类型及参数签名必须与父类方法的名称,返回类型及参数签名一致。

例:如下代码将会导致编译错误

public class Base {
    public void method(){
        
    }
}

public class Sub extends Base {
    public int method(){//编译错误,返回类型不一致
        return 0;
    }
}

若在子类中先将父类的method()方法覆盖,再重载,那么将是合法的。

public class Base {
    public void method(){
        
    }
}

public class Sub extends Base {
    
    public void method(){
        
    }
    public int method(int a){
        return 0;
    }

}

(2)子类方法不能缩小父类方法的访问权限。

例:如下代码将会导致编译错误。

public class Base {
    public void method(){
        
    }
}
public class Sub extends Base {
    
    private void method(){//编译错误,子类方法缩小了父类方法的访问权限
        
    }

}

错误原因分析:

    假如没有这个限制,将会与java多态机制发生冲突。如对于以下代码

Base base = new Sub();
base.method();

Java编译器认为以上是合法代码,在运行时候根据动态绑定规则,Java虚拟机会调用base变量所引用的Sub实例的method()方法,如果这个方法是private类型的,Java虚拟机就无法访问它。

(3)子类不能抛出比父类更多的异常。 子类抛出的异常必须和父类抛出的异常相同或者子类抛出的异常是父类抛出的异常的子类。

(4)方法覆盖只存在子类和父类(包括直接父类和间接父类)之间。 在同一个类中方法只能被重载不能被覆盖。

(5)父类的静态方法不能被子类覆盖为非静态方法。

例:如下代码将导致编译错误

public class Base {
    public static void method(){
        
    }
}

public class Sub extends Base {
    
    public void method(){ //编译出错
        
    }

}

(6)子类可以定义与父类的静态方法同名的静态方法。但须满足方法覆盖约束条件即方法的参数签名一致,返回类型一致,不能缩小父类方法的访问权限,不能抛出比父类方法更多的异常。

例:如下代码是合法的:

public class Base {
    static int method(int a) throws Exception{
        return 0;
    }

}

import java.io.IOException;

public class Sub extends Base {
    
    public static int method(int a) throws IOException{
        return 0;
    }

}

(7)父类的非静态方法不能被子类覆盖为静态方法。

public class Base {
    public void method(){
        
    }
}

public class Sub extends Base {
    
    public static void method(){ //编译出错
        
    }

}

(8)父类的私有方法不能被子类覆盖。

例:如下代码:

public class Base {
    private void say(){
        System.out.println("I am Base Class");
    }
    
    public void speak(){
        say();
    }
}
public class Sub extends Base {
    public void say(){
        System.out.println("I am Sub Class");
    }
    
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.speak();
    }

}

运行结果是:

I am Base Class

如果把Base类的say()方法改成public型的,即:

private void say(){
        System.out.println("I am Base Class");
    }

那么,运行结果为:

I am Sub Class

(9)父类的抽象方法可以被子类通过两种方式覆盖。

    1)子类实现父类的抽象方法

    2)子类重新声明父类的抽象方法

例:如下代码合法:

public abstract class Base {
    public abstract void method1();
    public abstract void method2();

}
public abstract class Sub extends Base {
    public void method1(){
        
    }
    
    public abstract void method2();

}

(10)父类的非抽象方法可以被覆盖为抽象方法

例:如下代码合法:

public class Base {
    void method(){
        
    }

}
public abstract class Sub extends Base {
    public abstract void method();

}