JavaSE-面向?qū)ο缶幊?/h2>

[TOC]

第一章:面向?qū)ο?概述

1.1-什么是面向?qū)ο螅?/h3>

概述

  • 面向?qū)ο笫且环N程序設(shè)計(jì)思想。
  • 程序設(shè)計(jì)的目的是為了用編程解決現(xiàn)實(shí)問題,而面向?qū)ο缶幊痰年P(guān)鍵在于強(qiáng)調(diào)對(duì)象,用什么對(duì)象來完成什么功能。
  • 在面向?qū)ο蟪绦蛟O(shè)計(jì)思想中,任何的事物都可以看作對(duì)象,也就是我們經(jīng)常所說的“萬物皆對(duì)象”(一部手機(jī)、一個(gè)人、一條狗等等都可以看做是對(duì)象)。
  • 對(duì)象是由屬性方法組成的。
    • 屬性:對(duì)象的狀態(tài)。
    • 方法:對(duì)象的行為或功能。
    • 圖解對(duì)象(比如:一個(gè)人)


面向?qū)ο缶幊趟枷?/strong>

? 面向?qū)ο缶幊趟枷刖褪?,將真?shí)世界的復(fù)雜關(guān)系,抽象為一個(gè)個(gè)對(duì)象,然后由對(duì)象之間的分工與合作,完成對(duì)真實(shí)世界的模擬。(總而言之,就是找對(duì)象做事兒)

  • 真實(shí)世界的復(fù)雜關(guān)系:明確需求
  • 抽象為一個(gè)個(gè)對(duì)象:劃分對(duì)象
  • 對(duì)象之間的分工與合作:
    • 分工:對(duì)象的功能
    • 合作: 對(duì)象之間的關(guān)系

面向?qū)ο缶幊痰奶攸c(diǎn)

  • 封裝:封裝(encapsulation)就是隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口,控制在程序中屬性的讀取和修改的訪問級(jí)別 。
  • 繼承: 繼承( inheritance)指的是 子類與父類的關(guān)系,子類可以繼承父類中的屬性和方法
  • 多態(tài): 多態(tài)(Polymorphism)按字面的意思就是“多種狀態(tài)”。在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。

關(guān)于對(duì)象的三大特征,后續(xù)會(huì)逐漸展開講解。

1.2-如何創(chuàng)建和使用對(duì)象?

上述講到,要面向?qū)ο缶幊?,就得找?duì)象做事兒。

找對(duì)象的前提,得先有對(duì)象。

現(xiàn)在沒有對(duì)象怎么辦?

那就得先創(chuàng)建對(duì)象,創(chuàng)建對(duì)象的規(guī)則,需要先知道如何定義

  • 類class,是對(duì)現(xiàn)實(shí)生活中一類具有共同特征的事物的抽象 。

比如,“狗”,“狗”是類,不是一個(gè)具體的對(duì)象,而是一個(gè)抽象的名稱或概念,泛指世界上“會(huì)汪汪叫”、“對(duì)主人忠誠”、"會(huì)看家護(hù)院"、“愛啃骨頭”、“有四條腿、兩只眼睛、一個(gè)鼻子、兩只耳朵等”具有這一系列特征的物種的稱呼。

所以,類,簡而言之就是一個(gè)抽象的概念;

對(duì)象

  • 對(duì)象,具有屬性方法的一個(gè)具體的實(shí)例。

類與對(duì)象的關(guān)系

  • 類是對(duì)象的模板,可以用來描述對(duì)象的屬性和方法。
  • 對(duì)象是類的一個(gè)具體實(shí)例。對(duì)象屬于類。

定義類

  • 關(guān)鍵字:class

  • 定義格式:

    public class 類名 {
        // 成員變量-描述對(duì)象的屬性
        // 成員方法-描述對(duì)象的方法
    }
    
  • 代碼演示:

    /* 定義類 */
    public class Dog {
      // 成員變量
      String name;
      String type;
      String color;
      // 成員方法
      public void eat(){
        System.out.println("我喜歡啃骨頭");
      }
      public void sound(){
        System.out.println("汪汪~~~");
      }
    }
    

注意:類名單詞的首字母要大寫(比如:Dog

創(chuàng)建和使用對(duì)象

  • 關(guān)鍵字:new

  • 創(chuàng)建格式:類名 對(duì)象名 = new 類名()

  • 使用對(duì)象:

    • 操作成員變量:
      • 獲取:對(duì)象名.成員變量
      • 設(shè)置:對(duì)象名.成員變量=值
    • 操作成員方法:
      • 調(diào)用方法:對(duì)象名.成員方法()
  • 代碼:

    public class DogTest {
      public static void main(String[] args) {
        // 創(chuàng)建對(duì)象
        Dog wangCai = new Dog();
        // 設(shè)置對(duì)象的屬性-成員變量
        wangCai.name = "旺財(cái)";
        wangCai.color = "黃色";
        wangCai.type = "中華田園犬";
        // 讀取對(duì)象的屬性
        System.out.println("這一條狗的名字:" + wangCai.name);
        System.out.println("這一條狗狗的毛色:" + wangCai.color);
        System.out.println("這一條狗狗的種族:" + wangCai.type);
        // 調(diào)用對(duì)象的方法
        wangCai.eat();
        wangCai.sound();
      }
    }
    
  • 注意:

    • 類是引用數(shù)據(jù)類型,而對(duì)象就是具體的數(shù)據(jù)。
    • 對(duì)象的命名和變量命名規(guī)則一樣。

1.3-成員變量的默認(rèn)值是什么?

  • 默認(rèn)值:


  • 代碼:

    public class DogTest02 {
      public static void main(String[] args) {
        Dog wangCai = new Dog();
        // 讀取對(duì)象的屬性
        System.out.println("這一條狗的名字:" + wangCai.name);  // null
        System.out.println("這一條狗狗的毛色:" + wangCai.color); // null
        System.out.println("這一條狗狗的種族:" + wangCai.type);  // null
      }
    }
    // 字符串是引用數(shù)據(jù)類型,索引默認(rèn)值是null
    

1.4-成員變量和局部變量的區(qū)別?

  • 成員變量:定義在類中的方法的變量。
  • 局部變量:定義在類中的方法內(nèi)的變量。
  • 區(qū)別:
    1. 位置不同
      • 成員變量,類中,方法外。
      • 局部變量,類中,方法內(nèi)
    2. 作用范圍不同
      • 成員變量,作用范圍-類中。
      • 局部變量,作用方法-方法中
    3. 默認(rèn)值不同
      • 成員變量,有默認(rèn)值。
      • 局部變量,沒有默認(rèn)值。并且,使用局部變量時(shí),局部變量必須賦值,否則編譯不通過。
    4. 內(nèi)存位置不同
      • 成員變量,堆區(qū)
      • 局部變量,棧區(qū)
    5. 生命周期不同
      • 成員變量,隨著對(duì)象的創(chuàng)建而創(chuàng)建,隨著對(duì)象的銷毀而銷毀。
      • 局部變量,隨著方法的調(diào)用而創(chuàng)建,隨著方法調(diào)用完畢而銷毀。

1.5-圖解內(nèi)存中的對(duì)象

一個(gè)對(duì)象創(chuàng)建并為屬性賦值的內(nèi)存圖

  • Person類代碼

    public class Person {
      // 成員變量
      String name;
      int age;
      // 成員方法
      public void eat(){
        System.out.println("吃飯");
      }
    }
    
  • PersonTest類代碼

    public class PersonTest {
      public static void main(String[] args) {
        Person zs = new Person();
        zs.name = "張三";
        zs.age = 10;
      }
    }
    
  • 內(nèi)存圖解

  • 總結(jié)

    1. 對(duì)象是引用數(shù)據(jù)類型的數(shù)據(jù)

一個(gè)對(duì)象調(diào)用方法的內(nèi)存圖

  • Person類代碼-同上

  • PersonTest類代碼

    public class PersonTest {
      public static void main(String[] args) {
        Person zs = new Person();
        zs.name = "張三";
        zs.age = 10;
        // 調(diào)用方法
        zs.eat();
      }
    }
    
  • 內(nèi)存圖解

  • 總結(jié)

    1. 調(diào)用方法時(shí),方法會(huì)入棧執(zhí)行,執(zhí)行完畢后會(huì)出棧。

兩個(gè)對(duì)象調(diào)用方法的內(nèi)存圖

  • Person類代碼-同上

  • PersonTest類代碼

    public class PersonTest {
      public static void main(String[] args) {
        Person zs = new Person();
        zs.name = "張三";
        zs.age = 10;
        zs.eat();
        Person ls = new Person();
        ls.name = "李四";
        ls.age = 11;
        ls.eat();
      }
    }
    
  • 內(nèi)存圖解

  • 總結(jié)

    1. new關(guān)鍵字創(chuàng)建對(duì)象時(shí),都會(huì)獨(dú)立開辟空間存放對(duì)象的信息。
    2. 所有對(duì)象的成員方法都是共享方法區(qū)中的class文件中的方法(節(jié)省內(nèi)存)。

第二章:面向?qū)ο?封裝

2.1-什么是封裝 ?

? 封裝(encapsulation)就是 隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口,控制在程序中屬性的讀取和修改的訪問級(jí)別 。

? 封裝的可以讓代碼更加健壯且易于維護(hù),提高程序的安全性。

2.2-如何封裝?

  • private關(guān)鍵字修飾成員變量

    • private修飾的成員變量,僅能夠在本類中使用。
    • 格式:private 數(shù)據(jù)類型 成員變量名;
  • 對(duì)外提供公開的getXXX/setXXX方法操作對(duì)象的屬性。

    • this關(guān)鍵字,在方法中表示調(diào)用方法的對(duì)象。
  • 代碼:

    public class Person {
      private String name;
      private int age;
    
      public String getName() {
        return name;
      }
      public void setName(String name) {
        this.name = name;
      }
      public int getAge() {
        return age;
      }
      public void setAge(int age) {
        this.age = age;
      }
    }
    
    

2.3-封裝優(yōu)化-構(gòu)造方法

什么是構(gòu)造方法-construction

  • 與類同名的方法

  • 方法修飾沒有返回值類型,沒有void。

    public class Person{
      // 無參構(gòu)造方法
        public Person(){
            
        }
    }
    

注意:類默認(rèn)有一個(gè)無參的構(gòu)造方法。構(gòu)造方法可重載

構(gòu)造方法的作用

  1. 創(chuàng)建對(duì)象。
    • 創(chuàng)建對(duì)象時(shí),會(huì)默認(rèn)調(diào)用類的無參構(gòu)造方法。
  2. 初始化對(duì)象的屬性值。
    • 可以定義帶參數(shù)構(gòu)造方法初始化對(duì)象屬性
  • 代碼:

    • Person類

      public class Person {
        private String name;
        private int age;
        // 無參數(shù)構(gòu)造方法
        public Person() {
        }
        // 有參數(shù)構(gòu)造方法
        public Person(String name, int age) {
          this.name = name;
          this.age = age;
        }
        public void show(){
          System.out.println("姓名:" + this.name);
          System.out.println("年齡:" + this.age);
        }
      }
      
      
    • 測試類

      public class PersonTest {
        public static void main(String[] args) {
          // 【調(diào)用無參構(gòu)造方法】
          Person zs = new Person();
          zs.name = "張三";
          zs.age = 10;
          zs.show(); // 打印結(jié)果:姓名:張三  年齡:10
          
          // 【調(diào)用有參構(gòu)造方法】
          Person ls = new Person("李四",12);
          ls.show(); // 打印結(jié)果:姓名:李四 年齡:12
        }
      }
      

2.4-JavaBean

? JavaBean 是 Java語言編寫類的一種標(biāo)準(zhǔn)規(guī)范。符合 JavaBean 的類,要求類必須是具體的和公共的,并且具有無參數(shù)的構(gòu)造方法,提供用來操作成員變量的 set 和 get 方法。

    public class 類名 {
        // 成員變量
        // 無參構(gòu)造方法【必須】
        // 有參構(gòu)造方法
        // get/set方法
        // 成員方法
    }

第三章:面向?qū)ο?繼承

3.1-繼承概述?

什么是繼承?

繼承是子類父類的關(guān)系,子類可以使用父類中的成員。

  • 父類:也叫基類或超類。
  • 子類:也叫派生類

例如:現(xiàn)實(shí)生活中的繼承


注意:

  • Java的繼承是單繼承,但支持多層繼承。


  • 所有的類都直接或間接的繼承了Object類

    • Object是祖宗類。
  • 對(duì)象 instanceof類 檢測一個(gè)對(duì)象是否屬于某個(gè)類。返回布爾值,true表示屬于,false表示不屬于。

    • Person類

      public class Person {
      }
      
    • PersonTest類

      public class PersonTest {
        public static void main(String[] args) {
          Person p1 = new Person();
          // p1屬于Person類
          System.out.println(p1 instanceof Person); // 結(jié)果:true
          // p1也屬于Object類
          System.out.println(p1 instanceof Object); // 結(jié)果:true
        }
      }
      

繼承的作用

  • 實(shí)現(xiàn)代碼的復(fù)用性。
  • 提高代碼的可擴(kuò)展性。

3.2-如何實(shí)現(xiàn)繼承?

關(guān)鍵字:extends

  • 格式

    public class 子類 extends 父類 {    
    }
    
  • 代碼:

    • 父類-手機(jī)類

      public class Phone {
        private String name;
        private int year;
        public Phone() {
        }
        public Phone(String name, int year) {
          this.name = name;
          this.year = year;
        }
        public String getName() {
          return name;
        }
        public void setName(String name) {
          this.name = name;
        }
        public int getYear() {
          return year;
        }
        public void setYear(int year) {
          this.year = year;
        }
        // 打電話功能
        public void  call(){
          System.out.println("打電話");
        }
        // 發(fā)短信
        public void sendMessage(){
          System.out.println("發(fā)送文字");
        }
        // 手機(jī)信息
        public void showInfo(){
          System.out.println("手機(jī)名稱:" + this.name);
          System.out.println("生產(chǎn)年份:" + this.year);
        }
      }
      
      
    • 子類-智能手機(jī)類

      /*智能手機(jī)類*/
      public class IntelligentPhone extends Phone {
        public IntelligentPhone() {
        }
        public IntelligentPhone(String name, int year) {
          super(name, year);
        }
        public void playMusic(){
          System.out.println("播放音樂");
        }
      }
      
    • 測試類

      public class Test {
        public static void main(String[] args) {
          IntelligentPhone iphone = new IntelligentPhone("iphone100",2100);
          iphone.call();  // 打電話
          iphone.sendMessage(); // 發(fā)送文字
          iphone.playMusic(); // 播放音樂
          iphone.showInfo(); // 手機(jī)名稱:iphone100 生產(chǎn)年份:2100
        }
      }
      
  • 關(guān)鍵字:super,在子類中表示父類的引用。

    • 在子類中調(diào)用父類構(gòu)造方法:super(參數(shù)列表)
    • 在子類中調(diào)用父類的非私有的成員變量:super.成員變量名
    • 在子類中調(diào)用父類的非私有的成員方法:super.成員方法()

3.3-方法的重寫-override

  • 子類中的方法和父類中的方法重名時(shí)(返回值和參數(shù)列表一致),叫做方法的重載

  • 代碼:

    • 父類-同上手機(jī)類

    • 子類

      public class IntelligentPhone extends Phone {
        public IntelligentPhone() {
        }
        public IntelligentPhone(String name, int year) {
          super(name, year);
        }
        public void playMusic(){
          System.out.println("播放音樂");
        }
      
        @Override
        // 重寫父類的方法sendMessage
        public void sendMessage() {
          // 調(diào)用父類的發(fā)送文字的功能
          super.sendMessage();
          // 擴(kuò)展發(fā)送圖片
          System.out.println("發(fā)送圖片");
        }
      }
      
    • 測試類

      public class Test {
        public static void main(String[] args) {
          IntelligentPhone iphone = new IntelligentPhone("iphone100",2100);
          iphone.sendMessage();
        }
      }
      // 結(jié)果:
      // 發(fā)送文字
      // 發(fā)送圖片
      

3.7-抽象類、抽象方法

抽象類和抽象方法的定義

  • 關(guān)鍵字:abstract
  • 抽象方法:只有聲明沒有方法體的方法。
    • 格式:public abstract 返回值類型 方法名(參數(shù)列表);
    • 一個(gè)抽象方法所在的類,該類一定是抽象類。
    • 抽象方法在子類中必須重寫,除非子類也是抽象類。
  • 抽象類:被abstruct關(guān)鍵字修飾的類。
    • 格式:public abstract class 類名{}
    • 抽象類不能被實(shí)例化(不能通過new關(guān)鍵字調(diào)用)。

什么時(shí)候適合使用抽象方法

  • 當(dāng)不同子類有相同的行為,但又有不同的具體實(shí)現(xiàn)時(shí),此時(shí)父類中定義方法時(shí)僅定義聲明即可。

  • 代碼:需求-創(chuàng)建一條狗對(duì)象和一只貓對(duì)象,它們有不同的叫聲

    • 父類-Animal

      public abstract class Animal {
        private String name;
        private int age;
        public Animal() {};
        public Animal(String name, int age) {
          this.name = name;
          this.age = age;
        }
        public void sleep(){
          System.out.println("睡覺~~~");
        }
        // 【抽象方法】不同的動(dòng)物,叫聲,所以讓子類重寫具體的方法體
        public abstract void shout();
        public String getName() {
          return name;
        }
        public void setName(String name) {
          this.name = name;
        }
        public int getAge() {
          return age;
        }
        public void setAge(int age) {
          this.age = age;
        }
      }
      
      
    • 子類-Cat

      public class Cat extends Animal {
        public Cat(){}
        public Cat(String name,int age){
          super(name,age);
        }
        @Override
        public void shout() {
          System.out.println(this.getName() + ":喵喵~~~");
        }
      }
      
    • 子類-Dog

      public class Dog extends Animal {
        public Dog(){};
        public Dog(String name,int age){
         super(name,age);
        }
        @Override
        public void shout() {
          System.out.println(this.getName() + ":汪汪~~~");
        }
      }
      
    • 測試類-Test

      public class Test {
        public static void main(String[] args) {
          Cat cat = new Cat("湯姆",2);
          cat.shout();  //結(jié)果: 湯姆:喵喵~~
          Dog dog = new Dog("旺財(cái)",3);
          dog.shout(); // 結(jié)果: 旺財(cái):汪汪~~
        }
      }
      

3.7-接口

概述

  • 接口,是一系列方法的集合。若類封裝了成員變量、成員方法、構(gòu)造方法,而接口主要封裝了方法。
  • 接口中可以定義抽象方法(jdk7之前)、默認(rèn)方法和靜態(tài)方法(jdk8)、私有方法(jdk9)以及常量。
  • 接口可以被實(shí)現(xiàn)(類似于被繼承),實(shí)現(xiàn)接口的類叫做實(shí)現(xiàn)類(類似于子類)。
  • 接口中的抽象方法,實(shí)現(xiàn)接口的類必須重寫。否則,實(shí)現(xiàn)類必須是抽象類。
  • 類可以實(shí)現(xiàn)多個(gè)接口。
  • 接口之間可以實(shí)現(xiàn)多繼承。

接口的定義和實(shí)現(xiàn)

  • 格式

    • 定義接口

      public interface 接口名稱{
          // 【抽象方法】
          public abstract 返回?cái)?shù)據(jù)類型 抽象方法名(參數(shù)列表);
          // 可簡寫為: 返回?cái)?shù)據(jù)類型 抽象方法名(參數(shù)列表);
          // 【默認(rèn)方法】
          public default 返回?cái)?shù)據(jù)類型 方法名(){
             // 方法體 
          }
          // 【靜態(tài)方法】
          public static 返回?cái)?shù)據(jù)類型 方法名(){
             // 方法體 
          }
          // 【私有方法】
          private 返回?cái)?shù)據(jù)類型 方法名(){
             // 方法體 
          }
      }
      
    • 實(shí)現(xiàn)接口:

      public class 實(shí)現(xiàn)類名 implements 接口1,接口2...接口n {
          // 重寫接口中的抽象方法【必須】
          // 重寫接口中的默認(rèn)方法【可選】
      }
      
    • 接口可以繼承其他接口

      public interface 接口1 extends 接口2,接口3...接口n{
          
      }
      
    • 注意:

      1. 抽象方法,實(shí)現(xiàn)類必須重寫
      2. 默認(rèn)方法,實(shí)現(xiàn)類可以繼承,也可以重寫(可選)
      3. 靜態(tài)方法,實(shí)現(xiàn)類和實(shí)現(xiàn)類的實(shí)例無法調(diào)用。接口名可以調(diào)用。
      4. 常量,實(shí)現(xiàn)類可以繼承。
      5. 私有方法,實(shí)現(xiàn)類無法繼承。
  • 代碼:

    • 接口

      public interface CommonInterface {
        // 常量
        public  final double VERSION = 1.0;
        // 抽象方法
        public abstract void fly();
        // 默認(rèn)方法
        public default void fn(){
          fn1();
          System.out.println("默認(rèn)方法");
        }
        // 私有方法
        private void fn1(){
          System.out.println("私有方法");
        }
        // 靜態(tài)方法
        public static void show(){
          System.out.println("靜態(tài)方法");
        }
      
      }
      
    • 實(shí)現(xiàn)類

      public class Bird implements CommonInterface {
        @Override
        public void fly() {
          System.out.println("展開翅膀飛行");
        }
      }
      
    • 測試類

      public class Test {
        public static void main(String[] args) {
          Bird xn = new Bird();
          xn.fly();
          xn.fn();
        }
      }
      

接口和抽象類的區(qū)別?

  • 相同點(diǎn)
    1. 都可以定義抽象方法。
    2. 都可以實(shí)現(xiàn)多態(tài)(第四章)。
    3. 都不可以被實(shí)例化。
  • 不同點(diǎn):
    1. 接口中不可定義成員變量、構(gòu)造方法、成員方法,抽象類可以。
    2. 接口可以多被多實(shí)現(xiàn)(類似多繼承)。抽象類僅支持單繼承。
    3. 接口可以多繼承其他接口。抽象類僅支持單繼承。

什么場景下用繼承類?什么場景下用實(shí)現(xiàn)接口?

  • 若強(qiáng)調(diào)多個(gè)類是什么時(shí),可以使用繼承。

  • 若強(qiáng)調(diào)多個(gè)類能做什么時(shí),可以使用實(shí)現(xiàn)接口。

第四章:面向?qū)ο?多態(tài)

4.1-什么是多態(tài)?

多態(tài)Polymorphism,按字面意思就是“多種狀態(tài)”。

面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài) 。

多態(tài)性是允許你將父對(duì)象設(shè)置成為一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作(摘自“Delphi4 編程技術(shù)內(nèi)幕”)。

簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。

4.2-多態(tài)的好處?

把不同的子類對(duì)象都當(dāng)作父類來看,可以屏蔽不同子類對(duì)象之間的差異,寫出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化。

4.3-如何實(shí)現(xiàn)多態(tài)?

實(shí)現(xiàn)多態(tài)的前提條件

  1. 繼承或者實(shí)現(xiàn)【二選一】
  2. 方法的重寫【意義體現(xiàn):不重寫,無意義】
  3. 父類引用指向子類對(duì)象【格式體現(xiàn)】

實(shí)現(xiàn)方式

  • 格式:父類或被實(shí)現(xiàn)的接口 變量名 = new 子類或?qū)崿F(xiàn)類()

  • 代碼:

    • 父類-Animal

      public abstract class Animal {
        private String name;
        private String type;
        public Animal(){}
        public Animal(String name,String type){
          this.name = name;
          this.type = type;
        }
        public abstract void sound();
        public String getName() {
          return name;
        }
        public void setName(String name) {
          this.name = name;
        }
        public String getType() {
          return type;
        }
        public void setType(String type) {
          this.type = type;
        }
      }
      
      
    • 子類-Bird

      public class Bird extends Animal {
        public Bird(){}
        public Bird(String name,String type) {
          super(name,type);
        }
        @Override
        public void sound() {
          System.out.println(this.getName() + ":嘰嘰喳喳~~");
        }
      }
      
    • 子類-Dog

      public class Dog extends Animal {
        public Dog(){}
        public Dog(String name,String type) {
          super(name,type);
        }
        @Override
        public void sound() {
          System.out.println(this.getName() + ":汪汪~~~");
        }
        public void play(){
          System.out.println("狗狗跳起來接飛盤!");
        }
      }
      
    • 測試類-Test

      public class Test {
        public static void main(String[] args) {
          AnimalSound(new Dog("旺財(cái)","中華田園犬"));  // 旺財(cái):汪汪~~~
          AnimalSound(new Bird("小咕","麻雀"));   // 小咕:嘰嘰喳喳~~
        }
        // 動(dòng)物的叫聲
        public static void AnimalSound(Animal animal){
          animal.sound();
        }
      }
      

4.4-向上向下轉(zhuǎn)型

還是上述代碼,若讓一個(gè)Dog對(duì)象指向父類的引用,再調(diào)用Dog的play方法時(shí),會(huì)編譯出錯(cuò)!

  • 代碼

    public class Test2 {
      public static void main(String[] args) {
        Animal animal = new Dog("旺財(cái)","中華田園犬");
        // animal.play(); // 編譯不通過
      }
    }
    

此時(shí)我們可以通過向下轉(zhuǎn)型為Dog對(duì)象,實(shí)現(xiàn)對(duì)象Dog對(duì)象獨(dú)有的方法調(diào)用。

  • 向上轉(zhuǎn)型:父類/接口 父類引用 = new 子類/實(shí)現(xiàn)類()
  • 向下轉(zhuǎn)型:(子類或?qū)崿F(xiàn)類)父類引用

代碼如下:

public class Test2 {
  public static void main(String[] args) {
    Animal animal = new Dog("旺財(cái)","中華田園犬");  // 向上轉(zhuǎn)型
    ((Dog) animal).play();  // 狗狗跳起來接飛盤!   // 向下轉(zhuǎn)型
  }
}
  • 注意:

    1. 向下轉(zhuǎn)型時(shí),若子類不對(duì)應(yīng),在運(yùn)行時(shí),會(huì)出現(xiàn)ClassCastException異常!

    2. 可以通過instanceOf方法檢測。

      public class Test2 {
        public static void main(String[] args) {
          Animal animal = new Bird("小咕","麻雀");
          // ((Dog) animal).play();  // ClassCastException 因?yàn)橄蛏限D(zhuǎn)型的子類對(duì)象不是Dog
          //【正確方式,先驗(yàn)證類型,再調(diào)用】
          if(animal instanceof Dog){
            ((Dog) animal).play();
          }
        }
      }
      

第五章:面向?qū)ο?其他

5.1-final關(guān)鍵字

若定義在父類中的某些成員變量或成員方法,不希望被子類修改,如何操作呢?

可以使用關(guān)鍵字final修飾

  • 成員變量
    • 被final修飾的成員變量必須初始化,否則編譯不通過。
    • 被final修飾的成員變量不能重復(fù)賦值。
  • 局部變量
    • 被final修飾的局部變量,若不賦值而使用會(huì)編譯不通過。
  • 成員方法
    • 被final修飾的成員方法,不能被重寫。
  • 成員類
    • 被final修飾的類,不能被繼承。

5.2-權(quán)限修飾符

概述

在Java中提供了四種訪問權(quán)限,使用不同的訪問權(quán)限修飾符修飾時(shí),被修飾的內(nèi)容會(huì)有不同的訪問權(quán)限,

  1. public:公共的。
  2. protected:受保護(hù)的
  3. default:默認(rèn)的
  4. private:私有的

不同權(quán)限的訪問能力

可見,public具有最大權(quán)限。private則是最小權(quán)限。

編寫代碼時(shí),如果沒有特殊的考慮,建議這樣使用權(quán)限:

  • 成員變量使用 private ,隱藏細(xì)節(jié)。
  • 構(gòu)造方法使用 public ,方便創(chuàng)建對(duì)象。
  • 成員方法使用 public ,方便調(diào)用方法。

5.3-內(nèi)部類

概述

內(nèi)部類和外部類:將一個(gè)類A定義在另一個(gè)類B里面,里面的那個(gè)類A就稱為內(nèi)部類,B則稱為外部類。

內(nèi)部類定義格式

class 外部類 {
    class 內(nèi)部類{ }
}

在描述事物時(shí),若一個(gè)事物內(nèi)部還包含其他事物,就可以使用內(nèi)部類這種結(jié)構(gòu)。比如,汽車類 Car 中包含發(fā)動(dòng)機(jī)

類 Engine ,這時(shí), Engine 就可以使用內(nèi)部類來描述,定義在成員位置。

class Car { 
    //外部類 
    class Engine {
        //內(nèi)部類 
    } 
}

訪問特點(diǎn)

  • 內(nèi)部類可以直接訪問外部類的成員,包括私有成員。
  • 外部類要訪問內(nèi)部類的成員,必須要建立內(nèi)部類的對(duì)象。

創(chuàng)建內(nèi)部類對(duì)象

格式:外部類名.內(nèi)部類名 對(duì)象名 = new 外部類型().new 內(nèi)部類型();

  • 人類

    public class Person { 
      private boolean live = true; 
      class Heart { 
          public void jump() { 
              // 直接訪問外部類成員
                if (live) { 
                  System.out.println("心臟在跳動(dòng)"); 
                } else { 
                  System.out.println("心臟不跳了"); 
                } 
             } 
        }
        public boolean isLive() { 
          return live; 
        }
        public void setLive(boolean live) { 
          this.live = live; 
          }       
    }
    
  • 測試類

    public class Test03   {
      public static void main(String[] args) { 
        // 創(chuàng)建外部類對(duì)象 
        Person p = new Person(); 
        // 創(chuàng)建內(nèi)部類對(duì)象 
        Heart heart = p.new Heart();
        // 調(diào)用內(nèi)部類方法 
        heart.jump(); 
        // 調(diào)用外部類方法 
        p.setLive(false); 
        // 調(diào)用內(nèi)部類方法 
        heart.jump(); 
      } 
    }
    // 輸出結(jié)果: 心臟在跳動(dòng) 心臟不跳了
    

內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后會(huì)內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名

$符號(hào) 。 比如,Person$Heart.class

匿名內(nèi)部類介紹

匿名內(nèi)部類 :是內(nèi)部類的簡化寫法。它的本質(zhì)是一個(gè) 帶具體實(shí)現(xiàn)的 父類或者父接口的 匿名的 子類對(duì)象。

開發(fā)中,最常用到的內(nèi)部類就是匿名內(nèi)部類了。以接口舉例,當(dāng)你使用一個(gè)接口時(shí),似乎得做如下幾步操作,

  1. 定義子類
  2. 重寫接口中的方法
  3. 創(chuàng)建子類對(duì)象
  4. 調(diào)用重寫后的方法

我們的目的,最終只是為了調(diào)用方法,那么能不能簡化一下,把以上四步合成一步呢?匿名內(nèi)部類就是做這樣的快

捷方式。

匿名內(nèi)部類的使用

  • 前提:匿名內(nèi)部類必須繼承一個(gè)父類或者實(shí)現(xiàn)一個(gè)父接口。

  • 格式

    new 父類名或者接口名(){ 
        // 方法重寫 
        @Override 
        public void method() { 
            // 執(zhí)行語句 
        } 
    };
    
  • 代碼

    • Fly接口

      public interface Fly {
        void fly();
      }
      
    • 測試類

      public class Test {
        public static void main(String[] args) {
         /*
           1.等號(hào)右邊:是匿名內(nèi)部類,定義并創(chuàng)建該接口的子類對(duì)象 
           2.等號(hào)左邊:是多態(tài)賦值,接口類型引用指向子類對(duì)象 
         */
          Fly bird = new Fly() {
            @Override
            public void fly() {
              System.out.println("小鳥飛...");
            }
          };
          // 調(diào)用匿名內(nèi)部類重寫后的方法。
          bird.fly();
      
        }
      }
      

匿名內(nèi)部類的作用

  • 是實(shí)現(xiàn)函數(shù)式編程的基礎(chǔ)

5.4-static關(guān)鍵字

概述

關(guān)于 static 關(guān)鍵字的使用,它可以用來修飾的成員變量和成員方法,被修飾的成員是屬于類的,而不是單單是屬

于某個(gè)對(duì)象的。也就是說,既然屬于類,就可以不靠創(chuàng)建對(duì)象來調(diào)用了。

類變量

當(dāng) static 修飾成員變量時(shí),該變量稱為類變量。該類的每個(gè)對(duì)象都共享同一個(gè)類變量的值。任何對(duì)象都可以更改

該類變量的值,但也可以在不創(chuàng)建該類的對(duì)象的情況下對(duì)類變量進(jìn)行操作。

  • 定義格式:修飾符 static 數(shù)據(jù)類型 變量名;
  • 舉例:修飾符 static int age

靜態(tài)方法

當(dāng) static 修飾成員方法時(shí),該方法稱為類方法 。靜態(tài)方法在聲明中有 static ,建議使用類名來調(diào)用,而不需要

創(chuàng)建類的對(duì)象。調(diào)用方式非常簡單。

  • 定義格式:static 返回值類型 方法名(參數(shù)列表){}

  • 代碼:

    public static void show(){
        System.out.println("hello");
    }
    

注意事項(xiàng):

  1. 靜態(tài)方法可以直接訪問類變量和靜態(tài)方法。
  2. 靜態(tài)方法不能直接訪問普通成員變量或成員方法。反之,成員方法可以直接訪問類變量或靜態(tài)方法。
  3. 靜態(tài)方法中,不能使用this關(guān)鍵字。

靜態(tài)代碼塊

  • 位置:類中方法外
  • 格式:static{}
  • 執(zhí)行:隨著類的加載而執(zhí)行且執(zhí)行一次,優(yōu)先于main方法和構(gòu)造方法的執(zhí)行。
  • 作用:給類變量進(jìn)行初始化賦值
public class ClassName{
    static { 
        // 執(zhí)行語句 
    } 
}

總結(jié)

static 關(guān)鍵字,可以修飾變量、方法和代碼塊。在使用的過程中,其主要目的還是想在不創(chuàng)建對(duì)象的情況

下,去調(diào)用方法。下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容