override 与 overload

“死党”是一种很不健康的朋友关系。确实,收获一名死党能让寂寞远离,但同时也意味着你将面临更多的选择:你不得不爱朋友之所爱,恶朋友之所恶。最终,你将变得不像你自己。而处于一个团队之中,最忌讳出现死党,当你的死党与某人翻脸时,试问你该如何处理与此人的关系呢?死党,在形成一段紧密关系的同时也与外界产生了隔阂。这是最近的一些生活感想。


Java 中有两种方式可以复用同一个方法名,这两种方式分别称为方法重写/覆盖 override 和方法重载/过载 overload,是 Java 多态性的不同体现。


定义:
方法重写/覆盖 override:override 是面向对象语言独有的特性,即父类中的一个方法在子类中获得重新定义,但是方法名、参数列表和返回值类型均维持不变。
方法重载/过载 overload:overload 是编程语言共有的特性,是指一个类(OOP)中多个方法拥有相同的方法名,但每个方法的参数列表互不相同。


override 和 overload 均表示同一个方法名对应多个方法实现体。但 override 发生在子类和父类之间,子类中 override 的方法的参数列表和返回值类型均与父类中被 override 的方法一致,并且子类不能对父类中被声明为 final 的方法进行 override,也不能在 override 时降低父类中对应方法的访问权限、抛出更多的异常(但可以减少异常);而 ovreload 发生在同一个类(当然,父类中 public 和 protected 权限的方法也是属于子类的方法)中,overload 方法和被 overload 的方法之间通过参数列表的差异(参数个数、参数类型、参数顺序等)来进行区分,需注意的是,返回值类型不是区分的条件。


Java 多态性的一些说明:
1 Java 多态性可以分为两种,静态的多态和动态的多态,也可称为编译时多态和运行时多态。所谓编译时多态就是指方法的 overload,而运行时多态就是方法的 override。
2 静态多态性。JVM 会在编译的时候根据方法的参数列表来决定调用哪一个方法,即静态多态性是在编译是确定的,引用类型决定了调用哪个版本的重载方法。
3 动态多态性。“一个接口,多个方法”,Java 实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译时调用重载方法的机制,此时对象而非引用的类型决定了调用子类还是父类中的方法。
4 对于 overload,表示新增了一个方法;对于 override,表示子类重写了父类的方法,子类不再拥有父类中的原方法,但可以通过 super 进行调用,子类中的方法数并未增加。
一个原则:当父类对象的引用指向子类对象时,形成动态多态性,子类对象的类型而不是引用的类型决定了调用谁的方法,但这个方法必须是在父类中定义过,因为一个引用只能调用该引用类型本身具有的方法和属性。也就是说,如果一个方法发生了 override,那么当通过子类对象来实例化父类的引用后,该引用在调用该方法时实际调用的将是子类中重写过的方法,尽管调用该方法的引用的类型为其父类。
5 当然,方法的调度遵循最精确匹配原则。


以下是一段及其恶心的示例:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 父类
 * 父类中存在两个 doWork 方法
 * @author dancen
 *
 */
class Parent
{
	/**
	 * @override
	 * @param workList
	 */
	public void doWork(ArrayList<Integer> workList)
	{
		System.out.println("Parent doWork with ArrayList ...");
	}
	
	/**
	 * 该方法在本类中形成第1次 overload
	 * @param workMap
	 */
	public void doWork(Map<Integer, String> workMap)
	{
		System.out.println("Parent doWork with Map ...");
	}
}

/**
 * 子类
 * 子类中存在4个 doWork 方法
 * @author dancen
 *
 */
class Child extends Parent
{
	/**
	 * 在父类中不存在参数列表相同的方法,该方法未形成 ovreride,而形成了第2次 overload
	 * 参数类型放宽,但毕竟参数类型不同了
	 * @param workList
	 */
	public void doWork(List<Integer> workList)
	{
		System.out.println("Child doWork with List ...");
	}
	
	/**
	 * 在父类中不存在参数列表相同的方法,该方法同样未形成 override,但形成了第3次 overload
	 * 参数类型收缩,但毕竟参数类型不同了
	 * @param workMap
	 */
	public void doWork(HashMap<Integer, String> workMap)
	{
		System.out.println("Child doWork with HashMap ...");
	}
	
	/**
	 * 该方法形成 override,同时也是一次 overload
	 * @param workList
	 */
	public void doWork(ArrayList<Integer> workList)
	{
		System.out.println("Child doWork with ArrayList ...");
	}
}

public class Test
{
	public static void main(String[] args)
	{
		test1();
		System.out.println("****************************");
		test2();
	}
	
	public static void test1()
	{
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		
		Parent p = new Parent();
		p.doWork(arrayList);	//调用父类中对应方法
		
		p = new Child();
		p.doWork(arrayList);	//发生 override,将通过对象类型,而非引用类型来决定调用的方法,因此调用的是子类中 override 的方法
		
		Child c = new Child();
		c.doWork(arrayList);	//调用子类中 override 的方法
	}
	
	public static void test2()
	{
		HashMap<Integer , String> hashMap = new HashMap<Integer , String>();
		
		Parent p = new Parent();
		p.doWork(hashMap);	//调用父类中对应方法
		
		p = new Child();
		p.doWork(hashMap);	//调用父类中对应方法
		
		Child c = new Child();
		c.doWork(hashMap);	//调用子类中对应方法
	}
}

输出结果:

Parent doWork with ArrayList ...
Child doWork with ArrayList ...
Child doWork with ArrayList ...
****************************
Parent doWork with Map ...
Parent doWork with Map ...
Child doWork with HashMap ...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值