【Java】谈谈Java中的覆盖和重载

重载和覆盖是 Java 多态性的不同表现方式,本文将介绍什么是重载(Overload)和覆盖(Override)以及二者之间的区别。

重载(Overload)

重载是在一个类里,方法名相同,而参数不同。返回的类型可以相同,也可以不同。每个重载的方法都必须有独一无二的参数列表。

最常用的地方就是构造器的重载

举个例子:

public class A {
	public int sum(int a) {
		return a;
    }
	public int sum(int a, int b) {
		return a + b;
	}
	public double sum(double a, double b) {
		return a + b;
	}
	public double sum(int a, double b, int c) {
		return a + b + c;
	}
	
	public static void main(String[] args) {
		A a = new A();
        
		int sum1 = a.sum(3);
		System.out.println(sum1); 
		
		double sum2 = a.sum(1, 2);
		System.out.println(sum2); 
		
		double sum3 = a.sum(1.0, 2.0);
		System.out.println(sum3);
		
		double sum4 = a.sum(1, 2.0, 3);
		System.out.println(sum4);
	}
}

上述代码中,有四个方法,方法名都是 sum。

方法名相同,参数列表不同,返回值的类型也不同,这就是方法的重载

需要注意的点

在使用重载时,需要注意以下几点:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

覆盖(Override)

覆盖(也叫重写)是指子类对父类允许访问的方法进行重新编写,返回值和形参都不可以改变。

也就是说,外壳不变,核心重写!

覆盖的好处在于,可以根据自己的需要定义属于自己的方法。

举个例子:

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
 
      a.move();// 执行 Animal 类的方法
 
      b.move();//执行 Dog 类的方法
   }
}

编译后运行结果:

动物可以移动
狗可以跑和走

在上面的例子中,我们 new 一个 Animal 对象,将它赋值给 Animal 引用,然后运行 move 方法。

然后 new 一个 Dog 对象,同样将它赋值给 Animal 引用,然后运行 move 方法。

从结果中可以看出,尽管 b 属于 Animal 类型,但是它仍然运行的是 Dog 类里的 move 方法。

原因是:在编译阶段,只是检查参数的引用类型,然而在运行的时候,JVM 指定对象的类型并运行该对象的方法。

因此在上面的例子中,之所以能够编译成功,是因为 Animal 类中存在 move 方法,然而运行的时候,运行的是特定对象的方法。

需要注意的地方

  • 参数列表必须完全与被重写方法的相同。
  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
  • 父类的成员方法只能被它的子类重写
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写
  • 如果不能继承一个方法,则不能重写这个方法

二者之间的区别

  • 重载是同一个类中方法之间的关系,是水平关系;覆盖是子类和父类之间的关系,是垂直关系
  • 重载是多个方法之间的关系;覆盖只能由一个方法或一对方法产生关系
  • 重载要求参数列表不同;覆盖要求参数列表相同
  • 重载关系是根据调用时的实参表与形参表来选择方法体;覆盖关系中,调用方法是根据对象的类型来决定

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值