java多态性

多态性,就是不同对象收到相同的消息时,产生不同的行为(即方法)。

  在C++中,多态性指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,这样就可以用同一函数名调用不同内容的函数。也就是说,可以用同样的接口访问功能不同的函数,从而实现“一个接口,多种方法”。

在java中,

1、Override 和 Overload 的区分

1)Override

在继承关系中,子类如果定义了一个与父类方法名、参数类型完全相同的方法,则被称为 Override。

子类可以覆写父类的方法,覆写在子类中改变了父类方法的行为。

在方法上加上“@Override”,可以让编译器帮助检查是否进行了正确的覆写。如果没有进行正确的覆写,则编译器会报错。但是“@Override”不是必需的。

2)Overload

如果方法的参数不同,就是Overload,Overload方法是一个 新的方法

注意:如果方法名相同、方法参数相同,但是方法的返回值不同,也是不同的方法,在Java程序中,出现这种情况,编译器会报错。

2、覆写(Override) Object 方法

所有的 class 最终都继承自 Object,而Object 定义了几个重要的方法:

  • toString():将 instance 输出为 String
  • equals():判断两个 instance 是否逻辑相等 (在实际项目中覆写过这个
  • hashCode():计算一个 instance 的哈希值

调用 super
在子类的覆写(Override)方法中,如果要调用父类的被覆写的方法,可通过 super 来调用。

3、final

继承可以允许子类覆写父类的方法,如果一个父类不允许子类对它的某方法进行覆写,可以将该方法标记为 final,用 final 修饰的方法不能被 Override。

被 final 修饰的类不能被继承、被 final 修饰的方法不能被重写(Override)、被 final 修饰的字段不能被更改。

4、多态

作用:将不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,抽象出一个通用的逻辑关系,以此来适应不同的业务需求。

针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。

public void runTwice(Person p){
	p.run();
}

上述代码中,传入的参数类型是 Person,但是我们无法知道传入的参数的实际类型是 Person,还是它的子类 Student,又或者是 Person 的其他子类,因此无法确定调用的是不是 Person 类定义的 run() 方法。

所以,多态 的特性就是,运行期才能动态地决定调用的子类方法。

问:这种不确定性的方法调用的作用是什么呢?
答:允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。
参考 廖雪峰——多态 中的代码

编译时多态 和 运行时多态

1)编译时多态:
在编译时就能够确定调用哪个方法。

  • 方法重载(Overload)时,都是编译时多态,在编译器可根据参数的数据类型、个数以及次序来确定调用方法。
  • 方法重写(Override)时,当 Student son = new Student(); 时,调用 son.name() 时为编译时多态。即,当对象引用本类实例时,为编译时多态;而 Person peo = new Student(); 时,调用 peo.name() 时为运行时动态。

2)运行时多态:
在运行时才能确定调用哪个方法

  • 方法重写(Override)时,当 Person val = new Student(); 时,调用 val.name(); 时,为运行时多态,因为此时只有在运行时,才能匹配到对应的方法进行调用。如果 Student类声明了 name() 方法,则执行;否则,执行 Person 类的 name() 方法。

代码如下:

class A {  
    public String show(D obj) {  
        return ("A and D");  
    }  
  
    public String show(A obj) {  
        return ("A and A");  
    }   
  
}  
  
class B extends A{  
    public String show(B obj){  
        return ("B and B");  
    }  
      
    public String show(A obj){  
        return ("B and A");  
    }   
}  
  
class C extends B{  
  
}  
  
class D extends B{  
  
}  
  
public class Test {  
    public static void main(String[] args) {  
        A a1 = new A();  
        A a2 = new B();  
        B b = new B();  
        C c = new C();  
        D d = new D();  
          
        System.out.println("1--" + a1.show(b));    //1--A and A
        System.out.println("2--" + a1.show(c));    //2--A and A
        System.out.println("3--" + a1.show(d));    //3--A and D
        System.out.println("4--" + a2.show(b));    //4--B and A
        System.out.println("5--" + a2.show(c));    //5--B and A
        System.out.println("6--" + a2.show(d));    //6--A and D
        System.out.println("7--" + b.show(b));     //7--B and B
        System.out.println("8--" + b.show(c));     //8--B and B
        System.out.println("9--" + b.show(d));     //9--A and D       
    }  
}  

重点在第四个测试输出。

看到大佬总结的一句话:
父类引用 指向 子类对象,只能调用 父类方法;但是当子类覆写了这个方法,就走子类的方法。

Java重载函数的选择只关注引用类型,不关注内存里面具体的类型,没有运行时多态的产生。

参考自:
廖雪峰——多态
一道Java程序输出题(继承-重载-覆盖-向上转型的问题)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值