文章目录
一、重载(Overload)
1、概念
在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了。
2、特点
2.1方法名必须相同
2.2方法的参数列表不同(参数的个数
不同,参数类型次序
不同,参数的类型
不同)。
举两个例子:
函数名相同,但参数个数不同或者参数类型不同。
public class Test {
public static int add(int x, int y){
return x+y;
}
public static int add(int y,int x,int z){ //函数名相同,参数个数不同
return y+x+z;
}
public static double add(double x, double y) { //函数名相同,参数类型不同
return x+y;
}
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 30;
double d= 10.2;
double e = 20.5;
int ret = add(a,b);
System.out.println("a+b="+ret);
int ret1 = add(a,b,c);
System.out.println("a+b+c="+ret1);
double ret2 = add(d,e);
System.out.println("d+e = "+ret2);
}
}
函数名相同,参数个数相同,参数类型相同,参数顺序不同
class Student{
public void print(String name,int age){
System.out.println("姓名:"+name+" 年龄:"+age);
}
public void print(int age,String name){ //参数个数相同,参数类型相同,但参数顺序不同
System.out.println("年龄:"+age+" 姓名:"+name);
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.print("张三",18);
student.print(20,"李四");
}
}
2.3与返回值类型是否相同无关。
3、 特别注意:以下情况不构成重载
1. 仅返回值类型不同 ❌
public int process() { return 42; }
public double process() { return 3.14; } // 编译错误!
原因: 在调用 process()方法
时,编译器无法确定你想要哪个返回值。
2. 仅参数名不同 ❌
public void setSize(int width) { }
public void setSize(int height) { } // 编译错误!
原因: 对编译器来说,这两个方法的签名都是 setSize(int)
,无法区分。
方法签名((补充)
经过编译器修改后方法的最终名字,具体方式:方法全路径名+参数列表+返回值类型,构成方法的完整名字。
3. 仅访问修饰符不同 ❌
public void calculate() { }
private void calculate() { } // 编译错误!
原因: 访问修饰符不同不影响方法签名。
4. 仅静态修饰符不同 ❌
public void show() { }
public static void show() { } // 编译错误!
原因: static
修饰符不同不构成重载。
4、重载的总结
构成重载的条件 (✅) | Java示例 |
---|---|
参数类型不同 | method(int) vs method(String) |
参数个数不同 | method() vs method(int) |
参数顺序不同 | method(int, String) vs method(String, int) |
可变参数 | method(String) vs method(String...) 以后学到再做补充 |
不构成重载的条件 (❌) | Java示例 |
---|---|
仅返回值不同 | int method() vs void method() |
仅参数名不同 | method(int a) vs method(int b) |
仅修饰符不同 | public method() vs private method() |
二、重写(Override)
1、概念
重写(Override):也称为覆盖。重写是子类对父类
非静态、非private、非final修饰,非构造方法等的实现过程进行重新编写。
2、特点
2.1 方法签名必须相同
- 方法名、参数列表(类型、数量、顺序)必须完全一致。
举个例子:
– Animal类
public abstract class Animal {
protected String name;
protected int age;
public abstract void eat();
}
–Cat类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println(this.name+"吃猫粮");
}
}
– Dog类
public class Dog extends Animal{
@Override
public void eat() {
System.out.println(this.name+"正在吃狗粮");
}
}
这里Animal的子类Dog类和Cat类都重写了父类的抽象eat()方法,其中参数列表(的类型、数量、顺序)完全一致,构成了重写。
2.2 返回值类型规则
- 基本类型:必须完全相同。
- 引用类型:可以是相同类型或具有父子关系的返回值类型可以不同。
举个例子:
– Animal类
public class Animal {
public Animal getAnimal(){
return new Animal();
}
}
– Dog类
public class Dog extends Animal{
@Override
public Dog getAnimal() {
return new Dog();
}
}
这里Animal类和它的子类Dog类返回值类型不同,但编译器并没有报错。
- 子类访问权限不能比父类中被重写的方法的访问权限更低。
举个例子:
– Animal类
public class Animal {
protected Animal getAnimal(){
return new Animal();
}
}
– Dog类
public class Dog extends Animal{
@Override
public Dog getAnimal() {
return new Dog();
}
}
父类访问权限是protected,子类是public,编译器没有报错,但如果子类是比父类访问权限低的,比如:default编译器就会报错。
- 父类被static、private修饰的构造方法都不能重写。
举个例子:
这里子类重写了父类Animal类被static关键字修饰的方法,编译器报错。
3、重写方法的总结
规则 | 要求 |
---|---|
方法签名 | 必须完全相同 |
返回类型 | 相同或具有父子关系的返回值类型可以不同 |
访问修饰符 | 不能比父类访问权限低 |
异常 | 不能抛出更宽泛的检查异常 |
final方法 | 不能重写 |
static方法 | 不能重写(只能隐藏) |
private方法 | 不能重写 |
构造方法 | 不能重写 |
核心思想:重写实现了运行时的多态性,让子类可以特定化父类的行为。
三、重载(Overload)和重写(Override)的对比
特性 | 方法重写 (Override) | 方法重载 (Overload) |
---|---|---|
方法名 | 必须相同 | 必须相同 |
参数列表 | 必须相同 | 必须不同 |
返回类型 | 必须相同或父子关系的返回值类型可以不同 | 可以不同 |
访问修饰符 | 不能比父类访问权限低 | 可以不同 |
抛出异常 | 不能更宽泛 | 可以不同 |
发生位置 | 父子类之间 | 同一类中 |
目的 | 多态实现 | 功能扩展 |