Java中的继承、方法覆盖和多态

一、继承

 关于java语言当中的继承:

  1.继承是面向对象三大特征之一,三大特征分别是:封装、继承、多态

  2.继承最”基本“的作用是:代码复用。但是继承最”重要“的作用是:有了

继承才有了以后”方法的覆盖“和”多态机制“。

  3.继承语法格式:

     【修饰符列表】 class 类名 extends 父类名{

              类体 = 属性 + 方法;

       }

  4.java语言当中的继承只支持单继承,一个类不能同时继承很多类,只能继承一个类,

在C++中支持多继承

 5.关于继承中的一些术语:

    B类继承A类,其中:

        A类称为:父类、基类、超类、superclass

        B类称为:子类、派生类、subclass

  6.在java语言当中子类继承父类都是继承哪些数据呢?

       -私有的不支持继承

       -构造方法不支持继承

       -其他数据都可以被继承

  7.虽然java语言当中只支持单继承,但是一个类也可以间接继承其他类,例如:

       C extends B{

       }

       B extends A{

       }

       A extends T{

       }

 8.java语言中假设一个类没有显示的继承任何类,该类默认继承JavaSE库当中提供的java.lang.Object类

 java语言当中任何一个类中都有Object类的特征

Myeclipse快捷键:查找类型【Open Type】-->ctrl+shift+t

Myeclipse快捷键:查找资源【Open Resource】-->ctrl+shift+r

 public class ExtendsTest{

    public static void main(String [] args){

       C c= new C();

       c.doSome();//这里调用的doSome方法是从B类中继承过来的doSome方法

       }

   }

 class A{

     public void doSome(){

        System.out.println("do Some");

     }

 class B extends A{

 }

 class C entends B{

 }

二、方法覆盖

回顾java语言当中的方法重载:

   1.方法重载又称为Overload

   2.方法重载什么时候使用?

       当在同一个类当中,方法完成的功能是相似的,建议方法名相同,这样方便程序员的编程,

就像在调用一个方法似的。代码美观。

   3.什么条件满足之后构成方法重载?

       *在同一个类当中

       *方法名相同

       *参数列表不同:类型,顺序,个数

   4.方法重载和什么无关?

      *和方法的返回值类型无关

      *和方法的修饰符列表无关

关于java语言当中方法的覆盖:

   1.方法覆盖又被称为方法重写,英语单词:override【官方的】/overwrite

   2.什么时候使用方法重写?

       当父类中的方法已经无法满足当前子类的业务需求,子类有必要将父类中继承过来的方法进行重新编写,这个重新编写的过程称为方法重写/方法覆盖。

  3.什么条件满足之后方法会发生重写呢?【代码满足什么条件之后,就构成方法的覆盖呢?】

     *方法重写发生在具有继承关系的父子类之间

     *方法重写的时候:返回值类型相同,方法名相同,形参列表相同

     *方法重写的时候:访问权限不能更低,可以更高。

     *方法重写的时候:抛出异常不能更多,可以更少。

   4.建议方法重写的时候尽量赋值粘贴,不要编写,容易出错,导致没有产生覆盖

   5.注意:

       私有方法不能继承,所以不能覆盖

       构造方法不能继承,所以不能覆盖

       静态方法不存在覆盖。

       覆盖只针对方法,不针对属性。

三、多态

关于java语言当中的多态语法机制:

   1.Animal Cat Bird三个类之间的关系:

          Cat继承Animal

          Bird继承Animal

          Cat和Bird之间没有任何继承关系

   2.面向对象三大特征:封装 继承 多态

   3.关于多态涉及到的概念:

       *向上转型(upcasting)

           子类型-->父类型  又被称为:自动类型装换

       *向下转型(downcasting)

           父类型-->子类型  又被称为:强制类型装换【需要加强制类型转换符】

       *无论是向上转换还是向下转换,两种类型之间必须要有继承关系,没有继承关系,程序是无法编译通过的。

 

 public class Test{

    public static void main(String[] args){

         //以前编写的程序

        Animal a1 = new Animal();

        a1.move();

        Cat c1 = new Cat();

        c1.move();

        c1.catchMouse();

        Bird b1 = new Bird();

        b1.move();

        //使用多态语法机制

        /*

            1.Animal和Cat之间存在继承关系,Animal是父类,Cat是子类

            2.Cat  is a Animal【合理的】

            3.new Cat()创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见他们进行了类型转换,子类型转换成父类型,称为向上转型/upcasting,或者称为自动类型装换

            4.Java中允许这种语法,父类型引用指向子类型对象

        */

         Animal a2 = new Cat();

         /*

            1.java程序永远都分为编译阶段和运行阶段。

            2.先分析编译阶段,再分析运行阶段,编译无法通过,根本是无法运行的

            3.编译阶段编译器检查a2这个引用的数据类型是Animal,由于Animal.class字节码当中有move()方法,所以编译通过了。这个过程我们称为静态绑定,编译阶段绑定。只有静态绑定成功之后才有后续的执行。

            4.在程序运行阶段,JVM堆内存当中真实创建的对象是Cat对象,那么以下程序在运行阶段一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定。

            5.无论是Cat类有没有重写move方法,运行阶段一定调用的是Cat对象的move方法,因为底层真实对象是Cat对象。

            6.父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的形态/状态,这种机制可以成为一种多态语法机制。

          */

           a2.move();

         /*

            分析以下程序为什么不能调用?

               因为编译阶段编译器检查到a2的类型是Animal类型,从Animal.class的字节码文件当中查找catchMouse()方法,最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。别谈运行了。

          */

           //a2.catchMouse();

          /*

              需求:

                   假设想让以上的对象执行catchMouse()方法,怎么办?

                      a2是无法直接调用的,因为a2的类型是Animal,Animal中没有catchMouse()方法。我们可以将a2强制类型转换为Cat类型。

               注:向下转型也需要两种类型之间必须有继承关系。不然编译报错。强制类型转换需要加强制类型转换符。

           什么时候需要使用向下转型呢?

                 当前调用的方法是子类型中特有的,在父类型当中不存在,必须进行向下转型。

        */

         Cat c2 = (Cat)a2;

         c2.catchMouse();   //猫抓老鼠!

         //父类型引用指向子类型对象【多态】

          Animal a3 = new Bird();

          /*

            1.以下程序编译是没有问题的,因为编译器检查到a3的数据类型是Animal,Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型,父类型装换为子类型叫做向下转型,语法合格。

            2.程序虽然编译通过了,但是程序在运行阶段会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型,Bird对象无法转换成Cat对象,因为两种类型之间不存在任何继承关系,此时会出现了著名的异常:java.lang.ClassCastException

             类型转换异常,这种异常总是在"向下转型”的时候会发生。

        */

         Cat c3 = (Cat)a3;

         /*

            1.以上异常只有在强制类型转换的时候会发生,也就是说“向下转换”存在隐患(编译通过了,但是运行出错了!)

            2.向上转型只要编译通过,运行一定不会出问题:Animal a = new Cat()

            3.向下转型编译通过,运行可能错误:Animal a3 = new Bird(); Cat c3 =(Cat)a3;

            4.怎么避免向下转型出现的ClassCastException呢?

               使用instanceof运算符可以避免出现以上的异常

            5.instanceof运算符怎么用?

                5.1语法格式:(引用 instanceof 数据类型名)

                5.2以上运算符的执行结果类型是布尔类型,结果可能是true/false

                5.3关于运算结果true/false:

                    假设:(a instanceof Animal)

               true表示:a这个引用指向的对象是一个Animal类型

               false表示:a这个引用指向的对象不是一个Animal类型

           6.Java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判断,避免ClassCastExpection异常的发生,这是一种编程的好习惯。

        */

          if( a3 instanceof Cat){   //a3是一个Cat类型的对象

              Cat c3 = (Cat)a3;

              //调用子类对象中特有的方法

             c3.catchMouse();

        }else if(a3 instanceof Bird){  //a3是一个Bird类型的对象

          Bird b2 = (Bird)a3;

             //调用子类对象中特有的方法

             b2.fly();

        }

   }

}

 

你可能感兴趣的:(java,开发语言)