JAVA 面试知识点 6 -- 面向对象编程( OOP)之多态(Polymorphism)

多态是OOP的另一个特点。是指一个名字有多种形态。
在java里面有两种多态:

  • compile-time polymorphism — method overloading
  • runtime polymorphism — method overriding

在java里的多态是用method overloading 和 method overriding来实现的。简单点来说就是:
用同一个方法的名字做了不同的事情

1.Method Overloading in Java
2.Method Overriding in Java
3. Overloading vs. Overriding

1. Method Overloading in Java

同一个类里面,允许有多个方法用同一个名字,但是不同的参数。 在 知识点3知识点4 里面讲过constructor overloading 。
不同参数的意思:

  • 个数不同
  • 参数类型不同
  • 参数顺序不同
    例子:
int add(int a, int b)
int add(int a, int b, int c)
int add(int a, float b)
int add(float a, int a)

注意:
只要parameters不同,返回值可以相同也可以不同,throws exception也不重要, public还是protected也不重要,是不是static的也不重要。
如果, 其中一个参数是另一个参数的子类算不算?
答案: 可以的!那如果传一个子类进去,调用哪个方法? 看例子:

public class OverloadTest {
    public String m1(A a) {
        return "first, para 'a' get";
    }
    public String m1(B b) {
       return "second, para 'b' get";
    }
    public static void main(String args[]) {
		OverloadTest ot = new OverloadTest();
		A a1 = new A();
		System.out.println(ot.m1(a1)); // first, para 'a' get
		B b = new B(); 
		System.out.println(ot.m1(b));// second, para 'b' get
		A a2 = new B();
		System.out.println(ot.m1(a2));// first, para 'a' get
   }
}
class A{}
class B extends A{} //b是a的子类

最后,关于static 关键词,其实不重要

static int add(int a, int b)
int add(int a, int b) //不行的,Compiler Error: cannot redefine add

最后的最后,overload是同一个类里面同样的方法名字不同的方法,但是方法可以是自己的,也可以是从父类那里继承来的。

2. Method Overriding in Java

关于override,已经在继承那里讲了好多了。继续详细讲一下怎么通过override实现runtime的多态的。

Runtime polymorphism 也可以看作是 Dynamic Method Dispatch 。 顾名思义就是在父类和子类里面有同样的方法,同样的参数,在runtime的时候才知道到底会调用哪一个。

对于overload,执行哪一个方法其实是显而易见的,数一数参数,哪一个方法对应上了就执行哪一个。但是在override的时候,尤其是reference的类型是实例类型的父类的时候(upcasting),这个就不太明显了,因为参数也是一样的。
看下面代码:

class Animal{}  
class Cat extends Animal{}  
Animal tom=new Cat(); // upcasting 

这个时候tom是一只猫,tom也是一只动物。tom这个名字的类型是Animal, 这个名字它指向的是一只猫。

这里主要讨论在override发生的时候,到底执行的是哪个类里的方法定义。

class Animal{  
	void eat(){System.out.println("eating...");}  
}  
class Dog extends Animal{  
	void eat(){System.out.println("dog eatting");}  
}   
class Poodle extends Dog{  
	void eat(){System.out.println("Poodle eating");}  
}  
public class TestPolymorphism3{  
	public static void main(String[] args){  
		Animal a;  
		a=new Dog();  
		a.eat();  
		a=new Poodle();  
		a.eat();   
	}
}  

输出:

dog eatting
Poodle eating

所以,reference的type不重要,执行的是实际的object的class里的方法。

来个大招:

class Animal{  
	void eat(){System.out.println("eating...");}  
}  
class Dog extends Animal{  
	void eat(){System.out.println("dog eatting");}  
}   
class Poodle extends Dog{  
	void eat(){System.out.println("Poodle eating");}  
}  
public class TestPolymorphism3{  
	public static void main(String[] args){  
		Animal a = new Poodle();  
		a.eat();
		Dog d = (Dog)a;
		d.eat();
		Poodle p= (Poodle)d;
		p.eat();
	}
}  

结果:

Poodle eating
Poodle eating
Poodle eating

由此可见,reference类型不重要,类型转化也不重要,执行哪个方法,只看被谁new出来的

3. Overloading vs. Overriding

OverloadingOverriding
同一个class里面用同一个方法名字不同的方法实现给从父辈继承来的方法提供不同的方法实现
可以是同一个class也可以是在父子类里面只发生在父子类里面
方法的参数不同方法的参数必须相同
可以有不同返回类型返回类型必须相同或者子类的返回类型是父类的返回类型的子类
access modifier 随意子类的access level 只能越来越大
throws出来的exception 随意子类抛出的异常需要是父类抛出异常的孩子,或者是抛出比父类少的异常
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值