讲一下重载和重写的区别?

参考回答**

重载(Overloading)和重写(Overriding)是 Java 中两个非常重要的概念,用于实现多态。它们的区别如下:

  1. 定义
    • 重载:同一个类中方法名称相同,但参数列表(参数个数或类型)不同。
    • 重写:子类对父类方法进行重新定义,方法名、参数列表都相同。
  2. 作用域
    • 重载:只发生在同一个类中。
    • 重写:发生在子类和父类之间。
  3. 方法签名
    • 重载:方法名相同,参数列表不同。
    • 重写:方法名、参数列表相同。
  4. 返回值
    • 重载:返回值可以相同或不同。
    • 重写:返回值必须与父类方法兼容(从 Java 5 开始可以是协变返回类型)。
  5. 访问修饰符
    • 重载:不受访问修饰符限制。
    • 重写:子类方法的访问修饰符不能比父类方法的访问修饰符更严格。
  6. 关键字
    • 重写:需要用到 @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) 方法。

注意点

  1. 静态方法不能被重写:因为静态方法是属于类的,不能通过实例实现运行时多态。
    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
       }
    }
    

    即使子类定义了同名的静态方法,这也不是重写,而是隐藏(方法遮蔽)。

  2. 构造方法不能被重写:构造方法是特定于类的,不能继承或重写,但可以通过方法重载实现构造器多样性。

拓展知识

  1. 协变返回类型:从 Java 5 开始,重写方法的返回类型可以是父类方法返回类型的子类。

    class Parent {
       public Number getNumber() {
           return 1;
       }
    }
    
    class Child extends Parent {
       @Override
       public Integer getNumber() {
           return 2;
       }
    }
    
  2. 性能影响

  • 重载的方法选择在编译期确定,对性能没有额外影响。
  • 重写的方法调用需要通过动态分派(virtual method table),可能略有性能损耗,但可以忽略不计。

总结表格

特性 重载(Overloading) 重写(Overriding)
发生范围 同一个类中 子类与父类之间
参数列表 必须不同 必须相同
返回类型 无要求 必须兼容(可以是协变类型)
修饰符要求 无限制 子类不能缩小父类的访问权限
静态方法支持 支持 不支持

发表评论

后才能评论