方法的重写与重载
序言
重载(Overloading)和重写(Overriding)是Java中两个比较重要的概念。但是对于新手来说也比较容易混淆,本文将对两者进行一个简单的举例说明,来区别他们之间的差别。
定义
重载:简单的说,就是函数或方法具有相同的名称,但是参数的列表不相同的情形,这样同名不同参数的函数或方法之间,互相成为重载函数或者方法。
重写:重写是指在Java的子类与父类之间有两个名称、参数列表都相同的情况下,由于他们具有相同的方法签名,所以子类中的新方法将覆盖父类中的原有方法。
重载 VS 重写
1、重载是在编译期的概念,而重写是在运行期间的概念;
2、重载遵循所谓的“编译期绑定”,即在运行的时候,即在编译时根据参数变量的类型判断应该调用哪个
方法。
3、重写遵循所谓的“运行期绑定”,即在运行的时候,根据引用变量所指向的实际对象的类型来调用方法。
4、因为在编译期已经确定了调用哪个方法,所以说重载不是多态。而重写是多态,重载只是一种语言的特性,是一种语法规则,与多态无关,与面向对象无关。
(注:严格的来说,重载是编译时的多态,静态多态,但是在Java中提到多态,在不特别说明的情况下都是指动态多态)
举例
重写的例子
public class NewClass1 {
public static void main(String[] args) {
Dog dog = new Hound();
dog.bark();
}
}
class Dog{
public void bark() {
System.out.println("woof");
}
}
class Hound extends Dog{
public void sniff() {
System.out.println("sniff");
}
public void bark() {
System.out.println("boof");
}
}
运行结果
debug:
boof
成功构建 (总时间: 0 秒)
感兴趣的大佬可以自己试一试
程序讲解:上面的实例中,dog对象被定义为Dog类型。那么在编译的时候,编译器会检查Dog类中是否有可以执行的bark()方法,只要是包含了bark方法,那么就可以编译通过。接下来到了运行期,Hound对象被实例化(new)出来,并赋值给dog变量,这时,Java虚拟机是知道dog变量指向的其实是Hound对象的引用。所以,当dog调用bark方法的时候,就会去调用Hound类中的bark方法。这就是所谓的动态多态性。
重写的条件
1、参数列表必须完全与被重写方法的相同;(参数相同)
2、返回类型必须完全与被重写方法方法的返回类型相同;(返回类型相同)
3、访问级别的限制性一定不能比被重写的方法强;
4、访问级别的限制性可以比被重写的方法弱;
5、重写方法一定不能抛出新的检查异常或比被重写的方法声明的检查异常更广泛的检查异常;
(重写的方法能够抛出更少或更有限的异常,也就是说,被重写的方法声明了异常,但重 写的方法可以什么也不声明)
6、重写不能被标示为final的方法;
7、如果不能继承一个方法,则不能重写这个方法;
那么我们就来看看重载的例子
public class NewClass2 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();
dog.bark(3);
}
static class Dog {
public void bark() {
System.out.println("woof");
}
public void bark(int num) {
for (int i = 0; i < num; i++) {
System.out.println("boof");
}
}
}
}
运行结果:
debug:
woof
boof
boof
boof
成功构建 (总时间: 0 秒)
上面的代码中,定义了两个 bark 方法,一个是没有参数的 bark 方法,另外一个是包 含一个 int 类型参数的 bark 方法。在编译期,编译期可以根据方法签名(方法名和参数情况)情况确定哪个方法被调用。
重载的条件:
1、被重载的方法必选改变参数列表;
2、被重载的方法可以改变返回类型;
3、被重载的方法可以改变访问修饰符;
4、被重载的方法可以声明新的或者更广的检查异常;
5、方法能够在同一个类中或者在一个子类中被重载;