您的位置:

JAVA中重载和重写的区别

一、JAVA重载和重写的区别

在JAVA中,重载(overload)和重写(override)是两个不同的概念。重载是指定义了多个同名的方法,但是参数的类型、个数或顺序不同,而重写是指子类覆盖了父类的同名方法。

重载方法在调用时会根据传入的参数类型、个数或顺序的不同,自动调用对应的方法。而重写方法则是在运行时根据实际对象的类型来决定调用哪个方法。

举个例子,假设我们有一个Animal类和它的子类Cat和Dog,Animal类中定义了一个名为speak的方法:

public class Animal {
    void speak() {
        System.out.println("动物叫声");
    }
}

public class Cat extends Animal {
    void speak() {
        System.out.println("喵喵喵");
    }
}

public class Dog extends Animal {
    void speak() {
        System.out.println("汪汪汪");
    }
}

在这个例子中,Animal中定义的speak方法是一个不带参数的方法。但是如果我们在Animal中再定义一个带参数的speak方法:

public class Animal {
    void speak() {
        System.out.println("动物叫声");
    }
    
    void speak(String language) {
        System.out.println("使用" + language + "叫声");
    }
}

那么这个时候,我们在调用speak方法时就需要根据传入的参数来决定使用哪个speak方法:

Animal animal = new Animal();
Cat cat = new Cat();
Dog dog = new Dog();

animal.speak(); // 输出:动物叫声
animal.speak("英语"); // 输出:使用英语叫声
cat.speak(); // 输出:喵喵喵
cat.speak("英语"); // 输出:使用英语叫声
dog.speak(); // 输出:汪汪汪
dog.speak("英语"); // 输出:使用英语叫声

二、JAVA重载和重写

1. 参数类型

参数类型是重载方法和被重写方法最显著的不同点。对于重载方法,它们必须拥有不同的参数类型。而对于被重写方法,子类方法必须完全匹配其父类方法的参数类型。

public class Animal {
    void speak() {
        System.out.println("动物叫声");
    }
    
    void eat() {
        System.out.println("动物吃东西");
    }
}

public class Cat extends Animal {
    void speak() {
        System.out.println("喵喵喵");
    }
    
    void eat(String food) {
        System.out.println("吃" + food);
    }
}

public class Dog extends Animal {
    void speak() {
        System.out.println("汪汪汪");
    }
    
    void eat(String food) {
        System.out.println("吃" + food);
    }
}

在这个例子中,Cat和Dog继承了Animal类,而Cat和Dog各自重写了eat方法,并且添加了一个字符串类型的参数。这时,我们在调用eat方法时,就需要传入一个字符串参数:

Animal animal = new Animal();
Cat cat = new Cat();
Dog dog = new Dog();

animal.eat(); // 编译错误:Animal类中没有eat()方法
cat.eat("鱼"); // 输出:吃鱼
dog.eat("骨头"); // 输出:吃骨头

2. 访问修饰符

访问修饰符也可以作为重载和重写方法的不同点之一。对于重载方法,它们可以有不同的访问修饰符。而对于被重写方法,子类方法不能缩小其父类方法的访问修饰符。

public class Animal {
    void speak() {
        System.out.println("动物叫声");
    }
    
    private void run() {
        System.out.println("动物奔跑");
    }
}

public class Cat extends Animal {
    public void speak() {
        System.out.println("喵喵喵");
    }
    
    // 编译错误:不能缩小访问修饰符
//  void run() {
//      System.out.println("猫跑步");
//  }
    
    public void run() {
        System.out.println("猫跑步");
    }
}

public class Dog extends Animal {
    public void speak() {
        System.out.println("汪汪汪");
    }
    
    // 编译错误:不能缩小访问修饰符
//  protected void run() {
//      System.out.println("狗跑步");
//  }
    
    public void run() {
        System.out.println("狗跑步");
    }
}

在这个例子中,Animal中定义了一个私有的run方法。Cat和Dog继承了Animal类,并分别重写了run方法,并尝试缩小其访问修饰符。但是,由于父类中run方法的访问修饰符是私有的,所以子类方法将不能访问这个方法。

3. 返回类型

返回类型也可以作为重载和重写方法的不同点之一。对于重载方法,它们可以有不同的返回类型。而对于被重写方法,子类方法的返回类型必须与其父类方法相同,或是其父类方法返回类型的子类。

public class Animal {
    Object speak() {
        System.out.println("动物叫声");
        return null;
    }
}

public class Cat extends Animal {
    // 编译错误:返回类型与父类不兼容
//  int speak() {
//      System.out.println("喵喵喵");
//      return 0;
//  }
    
    String speak() {
        System.out.println("喵喵喵");
        return "喵喵喵";
    }
}

public class Dog extends Animal {
    // 编译错误:返回类型与父类不兼容
//  String speak() {
//      System.out.println("汪汪汪");
//      return "汪汪汪";
//  }
    
    Object speak() {
        System.out.println("汪汪汪");
        return null;
    }
}

在这个例子中,Animal中定义了一个返回类型为Object的speak方法。Cat和Dog继承了Animal类,并尝试重写speak方法,并尝试使用不同的返回类型。但是,由于子类方法的返回类型必须与父类方法相同,或是其父类方法返回类型的子类,所以子类的做法是错误的。

三、JAVA中方法重写和重载的区别

JAVA中方法重写和重载是两个概念,但是由于它们都与方法有关,所以容易混淆。方法重写是子类覆盖了父类的同名方法,方法重载是在同一个类中定义了多个同名的方法,但是参数的类型、个数或顺序不同。

方法重写有一个重要的特点:动态绑定。子类实例在运行时会根据实际对象的类型来决定调用哪个方法。而对于方法重载,会根据参数类型、个数或顺序的不同,自动调用对应的方法。

因此,方法重写是实现多态的一个重要手段。而方法重载则更多地用于提供多种便利的方法调用方式。在实际开发中,我们需要根据实际需要选择是使用方法重载还是方法重写。