介绍
在 Java 中,重载(Overloading) 和 重写(Overriding) 是两个重要的概念,它们都与方法有关,但它们的应用场景和行为完全不同。
通过理解重载和重写的区别,可以更好地设计类的继承和方法的多态性。
重载
重载是指在同一个类中,允许存在多个方法名相同但参数列表不同的方法。重载的目的是为了提供方法的多态性,使得同一个方法名可以根据不同的参数类型或数量执行不同的逻辑。
特点
- 方法名相同:重载的方法必须具有相同的方法名。
- 参数列表不同:参数的类型、数量或顺序必须不同。
- 与返回值无关:重载与方法的返回值类型无关。
- 与访问修饰符无关:重载方法可以有不同的访问修饰符(如 public、private 等)。
- 发生在同一个类中:重载通常发生在同一个类中。
示例
java">class Calculator {// 重载方法:两个整数相加public int add(int a, int b) {return a + b;}// 重载方法:三个整数相加public int add(int a, int b, int c) {return a + b + c;}// 重载方法:两个浮点数相加public double add(double a, double b) {return a + b;}
}public class Main {public static void main(String[] args) {Calculator calc = new Calculator();System.out.println(calc.add(2, 3)); // 调用 add(int, int)System.out.println(calc.add(2, 3, 4)); // 调用 add(int, int, int)System.out.println(calc.add(2.5, 3.5)); // 调用 add(double, double)}
}
重写
重写是指子类重新定义父类中已有的方法。重写的目的是为了让子类可以根据自己的需求改变或扩展父类的行为。
特点
- 方法名相同:重写的方法必须与父类方法具有相同的方法名。
- 参数列表相同:重写的方法必须与父类方法具有相同的参数列表。
- 返回值类型相同或兼容:重写方法的返回值类型必须与父类方法相同或是其子类(协变返回类型)。
- 访问修饰符不能更严格:重写方法的访问修饰符不能比父类方法更严格(例如,父类方法是
protected,子类方法可以是 public 或 protected,但不能是 private)。 - 发生在父子类之间:重写发生在子类和父类之间。
- 不能重写 final 方法:如果父类方法是 final,则不能重写。
- 不能重写 static 方法:静态方法不能被重写,但可以隐藏(方法隐藏)。
示例
java">class Animal {public void makeSound() {System.out.println("Animal is making a sound");}
}class Dog extends Animal {@Override // 使用 @Override 注解表示重写public void makeSound() {System.out.println("Dog is barking");}
}public class Main {public static void main(String[] args) {Animal myDog = new Dog();myDog.makeSound(); // 输出: Dog is barking}
}
区别
注意事项
- @Override 注解:
在重写方法时,建议使用 @Override 注解,这样编译器会检查方法是否正确地重写了父类方法。
如果没有正确重写(例如参数列表不同),编译器会报错。
-
静态方法:
静态方法不能被重写,但可以在子类中定义一个与父类静态方法签名相同的静态方法,这称为方法隐藏。 -
构造方法:
构造方法不能被重写,但可以被重载。 -
协变返回类型:
从 Java 5 开始,重写方法的返回值类型可以是父类方法返回值类型的子类。
示例对比
重载示例
java">class MathUtils {int add(int a, int b) {return a + b;}double add(double a, double b) {return a + b;}
}
重写示例
java">class Animal {void sound() {System.out.println("Animal sound");}
}class Dog extends Animal {@Overridevoid sound() {System.out.println("Dog bark");}
}