讲一下重载和重写的区别?
参考回答**
重载(Overloading)和重写(Overriding)是 Java 中两个非常重要的概念,用于实现多态。它们的区别如下:
- 定义:
- 重载:同一个类中方法名称相同,但参数列表(参数个数或类型)不同。
- 重写:子类对父类方法进行重新定义,方法名、参数列表都相同。
- 作用域:
- 重载:只发生在同一个类中。
- 重写:发生在子类和父类之间。
- 方法签名:
- 重载:方法名相同,参数列表不同。
- 重写:方法名、参数列表相同。
- 返回值:
- 重载:返回值可以相同或不同。
- 重写:返回值必须与父类方法兼容(从 Java 5 开始可以是协变返回类型)。
- 访问修饰符:
- 重载:不受访问修饰符限制。
- 重写:子类方法的访问修饰符不能比父类方法的访问修饰符更严格。
- 关键字:
- 重写:需要用到
@Override
注解。 - 重载:无需特殊注解。
- 重写:需要用到
详细讲解与拓展
重载的细节
重载是方法的编译时多态,即方法的调用在编译期由参数列表决定。以下是一个示例:
public class OverloadingExample {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public String add(String a, String b) {
return a + b;
}
}
- 这里
add
方法重载了三次,分别接收不同类型的参数。 - 在编译时,编译器会根据传入的参数类型选择对应的方法。
重写的细节
重写是方法的运行时多态,由子类在运行期决定具体调用哪个方法。以下是一个示例:
class Parent {
public void display() {
System.out.println("Parent display method");
}
}
class Child extends Parent {
@Override
public void display() {
System.out.println("Child display method");
}
}
public class OverridingExample {
public static void main(String[] args) {
Parent obj = new Child();
obj.display(); // 输出:Child display method
}
}
- 这里
Child
类重写了Parent
类的display
方法。 - 在运行时,即使引用类型是
Parent
,实际调用的是子类的display
方法。
重载与重写的对比示例
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
// 重写父类方法
@Override
public void sound() {
System.out.println("Dog barks");
}
// 重载方法
public void sound(String type) {
System.out.println("Dog barks in a " + type + " way");
}
}
- 重写是子类重新定义
sound()
,满足多态的需求。 - 重载是通过不同参数列表定义了新的
sound(String type)
方法。
注意点
- 静态方法不能被重写:因为静态方法是属于类的,不能通过实例实现运行时多态。
class Parent { public static void staticMethod() { System.out.println("Static method in Parent"); } } class Child extends Parent { public static void staticMethod() { System.out.println("Static method in Child"); } } public class Test { public static void main(String[] args) { Parent obj = new Child(); obj.staticMethod(); // 输出:Static method in Parent } }
即使子类定义了同名的静态方法,这也不是重写,而是隐藏(方法遮蔽)。
-
构造方法不能被重写:构造方法是特定于类的,不能继承或重写,但可以通过方法重载实现构造器多样性。
拓展知识
-
协变返回类型:从 Java 5 开始,重写方法的返回类型可以是父类方法返回类型的子类。
class Parent { public Number getNumber() { return 1; } } class Child extends Parent { @Override public Integer getNumber() { return 2; } }
-
性能影响:
- 重载的方法选择在编译期确定,对性能没有额外影响。
- 重写的方法调用需要通过动态分派(virtual method table),可能略有性能损耗,但可以忽略不计。
总结表格
特性 | 重载(Overloading) | 重写(Overriding) |
---|---|---|
发生范围 | 同一个类中 | 子类与父类之间 |
参数列表 | 必须不同 | 必须相同 |
返回类型 | 无要求 | 必须兼容(可以是协变类型) |
修饰符要求 | 无限制 | 子类不能缩小父类的访问权限 |
静态方法支持 | 支持 | 不支持 |