一、前言
Java 面试题中可能有这样一道题:请简述方法重写和重载的区别?
:four_leaf_clover: 在之前的文章中介绍过【重载】:
Overloaded(重载) methods are differentiated by the number and the type of the arguments passed into the method. For example: run(String str)
and run(int i)
are distinct and unique methods because they require different argument types.
🌾 重载的方法通过传递给方法的参数的数量和类型来区分。
例如:run(String str)
和 run(int i)
是不同且独特的方法,因为它们拥有不同的参数类型。
🌾 重载:① 方法名相同,参数类型或参数数量不同;② 重载与返回值类型、参数名称无关
下面先介绍一下方法重写(Override),然后再总结它俩的区别。
二、方法重写(Override)
:sunflower: 重写:子类中的方法的方法签名与父类一样
:maple_leaf: 方法签名由 方法名和方法的 参数类型组成
:maple_leaf: 在同一个类中,方法签名是唯一的(同一方法签名的方法在同一个类中只能出现一次):sunflower: 方法重写也叫覆盖或覆写
方法重写例子:
public class Animal {
public void eat(String food) {
System.out.println("Animal - eat(" + food + ")");
}
public void run() {
System.out.println("Animal - run()");
}
public void jump() {
System.out.println("Animal - jump()");
}
}
public class Dog extends Animal {
@Override
public void eat(String thing) {
super.eat(thing);
run();
this.run();
super.run();
// 本类没有重写父类的 jump 方法
// 所以,调用的就是父类的 jump 方法
jump();
}
@Override
public void run() {
System.out.println("Dog - run()");
}
}
class TestDemo {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat("骨头");
}
/*
Animal - eat(骨头)
Dog - run()
Dog - run()
Animal - run()
Animal - jump()
*/
}
:herb: 子类重写(Override)的方法的权限(public、protected、private
)必须大于等于父类的方法权限
访问权限排名:public > protected > package-private > private
:herb: 子类重写(Override)的方法的返回值类型的范围必须小于等于父类的方法(被重写的方法)的返回值类型
:tada: 子类的范围 小于等于 父类
:tada:Object
是所有类的父类,Object
类的范围是最广的
public class Animal {
protected Object eat(String food) {
System.out.println("Animal - eat(" + food + ")");
return new Object();
}
}
class Dog extends Animal {
@Override
protected String eat(String food) {
super.eat(food);
return "我想上热榜";
}
}
三、super 关键字
:balloon: super 的作用:① 访问父类中定义的成员变量
② 调用父类中定义的方法(包括构造方法)
public class Animal {
private int value;
public Animal(int value) {
this.value = value;
}
/**
* 返回随机字符串
*/
public String returnRadomString() {
return UUID.randomUUID().toString();
}
}
class Dog extends Animal {
private String name;
public Dog(String name) {
super(666); // 调用父类的构造方法
// 调用父类的成员方法
System.out.println(super.returnRadomString());
this.name = name;
}
}
class TestDemo {
public static void main(String[] args) {
new Dog("大黄");
}
}
四、构造方法细节
:watch: 子类的构造方法必须先调用父类的构造方法,然后才执行自己后面的代码【之前的文章中有详细说明过】
public class Animal {
public Animal() {
System.out.println("Animal 父类的构造方法被调用");
System.out.println("Animal ------");
}
}
class Dog extends Animal {
public Dog() {
// super();
System.out.println("Dog 类的构造方法");
}
}
class TestDemo {
public static void main(String[] args) {
new Dog();
/*
Animal 父类的构造方法被调用
Animal ------
Dog 类的构造方法
*/
}
}
:blue_book: 子类中可以使用父类的成员变量
:blue_book: 父类的成员变量可能在 构造方法中进行初始化(构造方法的作用是初始化对象的属性)
:blue_book: 必须得先调用父类的构造方法把属性初始化完成后才调用子类的构造方法,这样子类中才可正确地使用父类的属性
:watch: 若子类的构造方法没有显式调用父类的构造方法:编译器会自动调用父类无参的构造方法(若此时父类没有无参的构造方法,编译器将报错)
五、方法重写(Override)
不同的资料对方法重写的介绍各不相同,但描述的重写的概念大同小异。我们应该博采众长、多看不同的资料。
:bookmark: 若子类存在一个方法 A::books:① 它的方法名、参数类型与父类的某个方法(如:B)一模一样;:books:② B 方法的返回类型等于 A 方法的返回值类型或是 A 方法的返回类型的子类型;则说 A 方法重写了 B 方法。
:bookmark: 子类的方法的形参列表、方法名必须和父类的方法的一模一样(与参数名无关)
:bookmark: 子类方法的返回类型要与父类方法的返回类型一样,或是父类方法返回类型的子类型
:bookmark: 子类方法不能缩小父类方法的访问权限
六、重写和重载的比较
若有错误,请不吝赐教!