实例方法
如果子类中存在实例方法A的方法签名与父类中实例方法B的相同,则称方法A覆盖了方法B。这里说的方法签名包括方法名、参数的个数和类型、方法的返回值类型。
子类可以通过方法覆盖的方式来修改父类中功能差不多的方法,以满足自身需要。新方法与被覆盖的方法具有相同的名称
参数个数、参数类型和返回值类型。不过,返回值类型不必一模一样,可以是源类型的子类型。比如原方法返回值类型为java.util.List,那么新方法可以返回java.util.ArrayList。这种返回类型也就是术语中的“协变返回类型”。
在写方法覆盖的时候最好加上@Override注解,来告诉编译器你在进行方法覆盖操作。如果编译器发现你写的代码并不是方法覆盖操作,则会抛出错误。
static方法
如果子类中存在静态方法staticA的方法签名与父类中静态方法staticB的相同,则称staticA隐藏了staticB。
静态方法的“隐藏”和实例方法的“覆盖”具有不同的效果:
- 实例方法依据实例类型来调用
- 静态方法依据声名类型来调用
下面用一个例子来说明一下静态方法与实例方法调用时遵循的规则。Animal类中包含一个静态方法和一个实例方法:
public class Animal{
public static void testClassMethod(){
System.out.println("The static method in Animal.");
}
public void testInstanceMethod(){
System.out.println("The instance method in Animal.");
}
}
下面Cat类是Animal的子类:
public class Cat extends Animal{
public static void testClassMethod() {
System.out.println("The static method in Cat.");
}
public void testInstanceMethod(){
System.out.println("The instance Method in Cat.");
}
public static void main(String[] agrs){
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
运行结果如下:
The static method in Animal.
The instance method in Cat.
接口方法
接口的默认实现方法与抽象方法的覆盖原理与类的实例方法相同。但是当子类同时既继承了父类又实现了多个父接口时,情况就有些复杂了。根据不同的情形,有如下几种不同的继承策略。
-
类的实例方法优先于接口的默认实现方法
class Horse{
public String identifyMyself(){
return "I am a horse.";
}
}
interface Flyer{
default public String identifyMyself(){
return "I am able to fly.";
}
}
interface Mythical {
default public String identityMyself(){
return "I am a mythical creature";
}
}
public class Pegasus extends Horse implements Flyer, Mythical{
public static void main(String[] args) {
Pegasus myApp = new Pegasus();
System.out.println(myApp.identifyMyself());
}
}
以上程序运行的结果为:
I am a horse.
- 已经被重写过得方法将不再被重写
interface Animal{
default public String identifyMyself(){
return "I am an animal.";
}
}
interface EggLayer extends Animal{
default public String identifyMyself(){
return "I am able to lay eggs.";
}
}
interface FireBreather extends Animal{ }
public class Dragon implements EggLayer, FireBreather{
public static void main(String[] args) {
Dragon myApp = new Dragon();
System.out.println(myApp.identifyMyself());
}
}
以上程序的运行结果为:
I am able to lay eggs.
分析:在Dragon的继承链中,Animal中的identifyMyself方法已经被继承链中的其他方法覆盖过了,所以要排除在候选方法外,则很显然只剩下了EggLayer中的identifyMyself方法。
- 如果以上两点排除完后还有冲突的方法存在,那么子类需要指明要重写的究竟是哪个父类方法
interface OperateCar{
default public String startEngine(){
return "operate engine.";
}
}
interface FlyCar{
default public String startEngine(){
return "fly engine.";
}
}
public class FlyingCar implements OperateCar, FlyCar{
public String startEngine(){
return OperateCar.super.startEngine() + FlyCar.super.startEngine();
}
public static void main(String[] args) {
FlyingCar myApp = new FlyingCar();
System.out.println(myApp.startEngine());
}
}
以上程序的输出结果为:
operate engine.fly engine.
分析:使用 接口名.super的方式可以指定需要调用的方法。