zoukankan      html  css  js  c++  java
  • Java 多态

      一、多态介绍

      继承提高了代码的重用性,让类和类之间建立的联系,为多态创造了条件。

      1、什么是多态

      多态是指,在程序中定义的引用变量所指向的具体类型在编程时并不确定,而是在程序运行期间才确定。

      由于在程序运行时才确定具体的类型,即不修改程序的代码就可以改变程序运行时所绑定的具体代码,让程序选择多个运行状态,这就是多态性。

      2、多态的分类(主要指运行期)

      编译时多态:方法重载,系统在编译时确定调用重载函数的哪个版本

      运行时多态:运行时多态基于面向对象的继承性实现,它指父类型的引用可以指向子类型的对象,这就是向上转型。通过一个父类的引用发出的方法调用,执行的方法可能是在父类中的实现,也可能是在子类中的实现,这由运行时刻具体的对象类型决定。

      3、向上转型

      首先理解,子类是父类的特殊化,每个子类的实例也是其父类的实例,但是反过来就不成立。

      所以向上转型就是在允许的继承关系中,可以将子类对象赋值给父类型的引用的特性。

           反过来,会导致编译时错误。

           并且,通过这个父类的引用访问子类的对象时,只能访问父类中拥有的方法和属性。因为编译器认为引用是父类中的引用。

    /*Bicycle是MountainBike的父类*/
    Bicycle myBike=new MountainBike();
    
    /*Object是所有类的父类*/
    Object obj=new MountainBike();

      

      4、向下转型

      即把上转型中的父类型引用又赋值给一个子类型的引用,指向的仍然是这个子类型的对象。

           必须是显示的,即强制类型转换。

    Object obj=new MountainBike();
    MountainBike myBike=(MountainBike) obj;

       这一转换编译器会通过,但是如果在运行时obj不是MountainBike类型,会抛出异常。

      所以在这种情况下,为了避免运行时异常,我们可以使用instanceof操作符做逻辑测试:

    if(obj instanceof MountainBike){
        MountainBike myBike=(MountainBike obj);
    }

      在一个深层次的继承关系中,这种判断分支是一个噩梦。因而在设计良好的程序中,应该尽量避免这种判断分支!

      5、方法重写(override) 

      (父类子类同名方法的返回类型、参数的个数、类型与顺序必须保持一致)

            返回类型可以不同,但必须兼容,比如父类中的类型为某个类的对象,子类中的方法可以返回这个类或者它的子类。

      父类的静态方法不能被子类重写为非静态;

      父类的非静态方法不能被子类重写为静态。

      二、多态的实现

      子类继承父类后,父类型的引用变量既可以指向父类对象,也可以指向子类对象。

      当相同的消息发给一个对象引用时,该引用会根据具体指向子类还是父类对象而执行不同的行为。

      多态性就是相同的消息使得不同的对象作出不同的响应的机制。

      Java中有两种形式实现多态:继承和接口(接口后面讲)

      1、继承实现多态(多态发生在有继承关系的父类和子类间)

      通过继承实现多态有三个条件:继承关系、方法重写和向上转型(子类对象的引用赋值给父类型的引用变量)。

      只有满足了3个条件,才能在一个继承结构中使用统一的逻辑代码处理不同的对象,从而达到执行不同的动作的目的。

      (具体执行父类对象还是子类对象的方法,你看指向的内存是哪个的实例就好了)

    public class Polymorphism {
        public static void main(String[] args) {
            Car sc = new ElectronicCar();
            sc.brake();
        }
    }
    class Car {
        public void brake() {
            System.out.println("SuperClass: I can brake.");
        }
    }
    class ElectronicCar extends Car {
        public void brake() {
            super.brake();
            System.out.println("SubClass: I can prevent collision~");
        }
    }

       我们再看一个例子,更好地体会多态的优点:无论Car的子类如何变化,调用接口brakeInterface()保持不变。当brakeInterface()是给第三方使用时,接口方法保持稳定,可以不影响第三方的代码。

    package test;
    
    public class Polymorphism {
        public static void main(String[] args) {
            Car sc = new Car();
            brakeInterface(sc);
            sc=new ElectronicCar();
            brakeInterface(sc);
            sc=new HoveringCar();
            brakeInterface(sc);
        }
    
        public static void brakeInterface(Car sc){
            sc.brake();
        }
    }
    class Car {
        public void brake() {
            System.out.println("SuperClass: I can brake.");
        }
    }
    class HoveringCar extends Car{
        public void brake(){
            super.brake();
            System.out.println("This is Hovering car~ ");
        }
    }
    class ElectronicCar extends Car {
        public void brake() {
            super.brake();
            System.out.println("SubClass: I can prevent collision~");
        }
    }

      2、关于equals()方法

      操作符“==”可以比较两个基本类型的变量是否相等。

      当我们使用它比较两个对象的引用变量,实际上实在比较两个引用变量是否指向了相同的对象。这里,相同的对象是指在堆中占用同一块内存单元中的同类型对象。

      如何比较两个对象的引用变量所指向的对象的内容是否相同?

      使用equals()方法(Object类中定义了,意味着每个类都会有这个方法),返回boolean。

      但是默认情况下,它比较的是对象的引用是否相同。

      String、Integer、Date中,equals()方法被重写了,比较的不是内存中的地址而是对象的内容。

      在自定义的类的对象中,equals()比较两个引用是否指向了同一个对象。因此,如果想比较对象的内容,在类中重写equals()吧!

      

  • 相关阅读:
    微信小程序实现运动步数排行(可删除)
    微信小程序实现运动步数排行(可删除)
    一个文艺的在线生成漂亮的二维码工具网站
    微信小程序常见的UI框架/组件库总结
    天天快车是款精细的游戏
    MHA的几种死法-叶良辰
    编译maxscale
    mydbtest文档
    高山仰止
    docker居然需要3.10以上的内核
  • 原文地址:https://www.cnblogs.com/bigbigbigo/p/8421784.html
Copyright © 2011-2022 走看看