zoukankan      html  css  js  c++  java
  • Java面向对象(五):OOP三大特性之多态 — final 关键字

    一、多态 

       理解:多态本意是指同一事物在不同的条件会有不同的形态;

    映射到Java中可以理解为:同一个父类方法被不同的子类调用,会产生不同的行为(重写父类的方法);

    也可表述为:不同子类的对象对父类同一消息能做出不同的响应(重写父类的方法)。 即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。

    1、面向对象的多态的实现前提:

    (1)要有继承:类与类之间必须有继承关系;

    (2)要有重写:子类重写父类的成员方法(可以不重写,但这就失去了多态的意义);

    (3)向上转型:父类引用可以指向任何一个子类的对象。

    2、向上转型(子类自动转为父类):子类"伪装"成父类,执行子类的方法;

    class Fu { 

      ..... 

    class Zi extends Fu {

       .....

          Fu  fu      =   new Zi();

    父类  父类引用 =  子类对象 

    注:

    1、Java指向的两个时期:编译器与执行器,编译期看类型,执行期看对象。

    2、多态调用函数的处理过程: 编译器从父类查找是否有该函数,没有的话报错,有的话在执行期执行子类中重写的同名函数,而不是父类。 

    例程:duotai包:ZMS.java ZMSSON.java

    3、向下转型(父类强制转化为子类):"伪装"成父类的"子类"还原成真正的子类

    Zi zi = (Zi) fu; //类似于强制转换大范围到小范围 

    例程:duotai包:ZMS.java ZMSSON.java

    ZMS.java

     1 package duoTai;
     2 
     3 public class ZMS {
     4     String name;
     5     int age;
     6 
     7     public void teach() {
     8         
     9         System.out.println("我是父类ZMS教Java");
    10     }
    11     
    12     public void show() {
    13         System.out.println(name+age);
    14         
    15     }
    16     
    17 }
    View Code

    ZMSSON.java

     1 package duoTai;
     2 /**
     3  * 创建ZMS子类
     4  * 多态的测试
     5  * 
     6  * */
     7 public class ZMSSON extends ZMS {
     8     
     9     //重写父类中同名方法
    10     public void teach() {
    11         
    12         System.out.println("我是ZMS子类教文学");
    13     //    like();
    14     }
    15     
    16     //子类自己的成员方法
    17     public void like() {
    18         System.out.println("ZMSSON喜欢踢球");
    19         
    20     }
    21     
    22     public static void main(String[] args) {
    23     
    24         /*
    25          * 多态的表示:父类 父类引用名 = 子类对象
    26          * 多态调用函数的处理过程: 编译器从父类查找是否有该函数,没有的话报错,
    27          *                                                 有的话在执行期执行子类中重写的同名函数,而不是父类。
    28          * 
    29          * */
    30         ZMS zmsText = new ZMSSON();
    31         zmsText.teach();
    32         
    33         //调用不了父类没有的方法
    34         //zmsText.like();
    35     
    36         //调用父类的成员变量方法
    37         zmsText.name = "zms";
    38         zmsText.age = 65;
    39         zmsText.show();
    40     
    41         //
    42         ZMSSON zmsSon = (ZMSSON) zmsText;
    43         zmsSon.teach();
    44         zmsSon.like();
    45         
    46     }
    47     
    48 }
    View Code

    4、多态的好处:

    (1)提高了代码的复用性(继承)

    (2)提高了代码的扩展性(多态)

    5、instanceof 关键字:

          boolean b = a instanceof b;

          判断a类是否属于另一个b类,是返回true,否则返回false。

     练习:跟据从键盘输入数字不同选择不同的子类对象,执行不同的响应(重点理解);   

    例程:duotai包:Animal.java duoTaiAnimal.java

    创建父类:

     1 package duoTai;
     2 
     3 public class Animal {
     4     public String name ;
     5     public int age;
     6     
     7     public void eat() {
     8         System.out.println(name+"动物吃东西");
     9     }
    10     
    11 }
    View Code

    创建两个子类:

     1 package duoTai;
     2 
     3 public class Cat extends Animal{
     4     
     5     //重写父类方法
     6     public void eat() {
     7         System.out.println("猫吃鱼");
     8         
     9     }
    10     
    11     //写子类自己的方法
    12     public void catchMouse() {
    13         System.out.println("抓老鼠");
    14     }
    15     
    16 }
    17 
    18 
    19 // 在另一个java文件中创建
    20 package duoTai;
    21 
    22 public class Dog extends Animal{
    23         
    24        //重写父类方法
    25         public void eat() {
    26             System.out.println("吃狗粮");
    27         }
    28         
    29         //写子类自己的方法
    30         public void kanMen() {
    31             System.out.println("狗看门");
    32         }
    33 }
    View Code

      创建测试功能类:  

     1 package duoTai;
     2 
     3 /**
     4  * @author  Kanekiyi
     5  * 理解多态的意义:同一消息(函数)可以根据发出的对象不同而产生不同的行为方式。
     6  *                          Or   不同的对象调用同一个函数能够产生不同的行为方式。
     7  */
     8 import java.util.Scanner;
     9 
    10 public class duoTaiAnimal {
    11     
    12     @SuppressWarnings("resource")
    13     public static void main(String[] args) {
    14         
    15         System.out.println("请输入数字1选择猫,数字2选择狗");
    16         Scanner sc  = new Scanner(System.in);
    17 
    18         int num = sc.nextInt();
    19         Animal animal = new Animal();
    20         /*
    21          * 向上转型时,根据指令选择不同的对象源
    22          */
    23         if (num == 1) {
    24             animal = new Cat();
    25         }    else if (num == 2) {
    26             animal = new Dog();
    27         }    else {
    28             System.out.println("输入数字错误请重新输入数字1或者2");
    29         }
    30         
    31         runAnimal ( animal);
    32         
    33     }
    34     
    35     public static  void runAnimal(Animal a) {
    36         
    37         //根据对象的不同执行子类重写的eat()方法;
    38         a.eat();                                
    39         
    40         /*
    41          * 向下转型时,注意转型目标子类类型是否符合
    42          * 目的:执行子类中特有的功能
    43          *          
    44          */
    45         
    46         if (a instanceof Cat) {
    47             Cat cat = (Cat) a;
    48             cat.catchMouse();
    49             
    50         }    else if (a instanceof Dog) {
    51             Dog dog = (Dog) a;                                    
    52             dog.kanMen();
    53             
    54         }    else {
    55             System.out.println("输入错误,不属于cat类也不属于Dog类");
    56         }
    57         
    58     }
    59 
    60 }
    View Code

    二、final 关键字

    2.1 final修饰类

      final修饰的类不能被继承;

    2.2 final修饰变量

    final 变量能被显式地初始化并且只能初始化一次。被声明为 final 的对象的引用不能指向不同的对象,但是 final 对象里的数据可以被改变。也就是说 final 对象的引用不能改变,但是里面的值可以改变。(存疑)。

    final与static一起修饰成员变量构成常量,声明的时候常量名全部大写,可以直接通过类名访问。

    例程:

     1 package Fianal;
     2 
     3 
     4 //public class Final1 extends Final0{        final修饰的类不能够被继承
     5 public class Final1 {
     6     
     7     int IDCard ;
     8      //final修饰的成员变量声明时初始化且有且只初始化一次。
     9     final int IDCardNum =314;         
    10     final int IDCardNum1;                                 
    11 
    12     static final String IDCARD= "36452345245X";
    13     
    14     //通过构造函数给final修饰的成员变量初始化
    15     public Final1() {
    16         super();
    17         IDCardNum1 =314; 
    18         
    19     }
    20 
    21     public final void textMath() {
    22         
    23         System.out.println("我是Final1类的final方法");
    24     }
    25     
    26      
    27 }
    View Code

    2.3 final 修饰方法

    final 修饰成员方法,可以被子类继承,但是不能被重写;

    注:

    1、final 修饰的成员变量初始化的两种方式:

    1) 声明时就初始化;

    2)通过构造函数初始化。

    且只初始化一次,初始化后就不能修改。

    2、final 修饰的变量为常量时,在加载时系统会将变量替换为其所表示的常量。

    例程:

     1 package Fianal;
     2 
     3 public class Final2 extends Final1 {
     4     
     5     //父类final修饰的成员方法不能重写,只能调用
     6     //public final void textMath() {}
     7     
     8     public static void main(String[] args) {
     9         Final2 textFinal = new Final2();
    10         textFinal.IDCard = 2;
    11         
    12         //final修饰的变量在声明时就初始化且只能初始化一次,只能被调用不能被修改
    13         //textFinal.IDCardNum = 3;
    14         System.out.println("普通成员变量IDCard:"+textFinal.IDCard);
    15         System.out.println("final修饰的成员变量IDCardNum:"+textFinal.IDCardNum);
    16         //System.out.println("final和static修饰的成员变量IDCARD:"+textFinal.IDCARD);
    17         //常量可以直接调用或类名调用
    18         System.out.println("final和static修饰的成员变量IDCARD:"+Final1.IDCARD);
    19         System.out.println("final和static修饰的成员变量IDCARD:"+IDCARD);
    20 
    21         textFinal.textMath();
    22         
    23     }
    24     
    25 }
    View Code

     

  • 相关阅读:
    Kafka源码分析9:Controller控制器的原理(图解+秒懂+史上最全)
    nacos高可用 (史上最全 + 图解+秒懂)
    Kafka源码分析11:PartitionStateMachine分区状态机(图解+秒懂+史上最全)
    Kafka源码分析2:Kafka产品选择和Kafka版本选择(史上最全)
    Kafka源码分析10:副本状态机ReplicaStateMachine详解 (图解+秒懂+史上最全)
    Netty解决Selector空轮询BUG的策略(图解+秒懂+史上最全)
    Kafka源码分析1:源码的开发环境搭建 (图解+秒懂+史上最全)
    mysql pxc集群 原理 (图解+秒懂+史上最全)
    seat TCC 实战(图解_秒懂_史上最全)
    seata 源码解析(图解_秒懂_史上最全)
  • 原文地址:https://www.cnblogs.com/Kanekiyi/p/9508685.html
Copyright © 2011-2022 走看看