【Java】內部類


內部類分爲四種:

  • 非靜態內部類
  • 靜態內部類
  • 匿名類
  • 本地類

非靜態內部類

非靜態內部類 BattleScore “戰鬥成績”
非靜態內部類可以直接在一個類裏面定義

比如:
戰鬥成績只有在一個英雄對象存在的時候纔有意義
所以實例化BattleScore 的時候,必須建立在一個存在的英雄的基礎上
語法: new 外部類().new 內部類()
作爲Hero的非靜態內部類,是可以直接訪問外部類的private實例屬性name的

package charactor;
 
public class Hero {
    private String name; // 姓名
    float hp; 			 // 血量
    float armor; 		 // 護甲
    int moveSpeed; 		 // 移動速度
    // 非靜態內部類,只有一個外部類對象存在的時候,纔有意義
    // 戰鬥成績只有在一個英雄對象存在的時候纔有意義
    class BattleScore {
        int kill;
        int die;
        int assit;
         public void legendary() {
            if (kill >= 8)
                System.out.println(name + "超神!");
            else
                System.out.println(name + "尚未超神!");
        }
    }
    public static void main(String[] args) {
        Hero garen = new Hero();
        garen.name = "蓋倫";
        // 實例化內部類
        // BattleScore對象只有在一個英雄對象存在的時候纔有意義
        // 所以其實例化必須建立在一個外部類對象的基礎之上
        BattleScore score = garen.new BattleScore();
        score.kill = 9;
        score.legendary();
    }
}

靜態內部類

在一個類裏面聲明一個靜態內部類
比如敵方水晶,當敵方水晶沒有血的時候,己方所有英雄都取得勝利,而不只是某一個具體的英雄取得勝利
與非靜態內部類不同,靜態內部類水晶類的實例化 不需要一個外部類的實例爲基礎,可以直接實例化
語法:new 外部類.靜態內部類();
因爲沒有一個外部類的實例,所以在靜態內部類裏面不可以訪問外部類的實例屬性和方法
除了可以訪問外部類的私有靜態成員外,靜態內部類和普通類沒什麼大的區別

package charactor;
  
public class Hero {
    public String name;
    protected float hp;
  
    private static void battleWin(){
        System.out.println("battle win");
    }
     
    //敵方的水晶
    static class EnemyCrystal{
        int hp=5000;
         
        //如果水晶的血量爲0,則宣佈勝利
        public void checkIfVictory(){
            if(hp == 0){
                Hero.battleWin();
                 
                //靜態內部類不能直接訪問外部類的對象屬性
                // System.out.println(name + " win this game");
            }
        }
    }
     
    public static void main(String[] args) {
        //實例化靜態內部類
        Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
        crystal.checkIfVictory();
    }
  
}

匿名類

匿名類指的是在聲明一個類的同時實例化它,使代碼更加簡潔精練
通常情況下,要使用一個接口或者抽象類,都必須創建一個子類

有的時候,爲了快速使用,直接實例化一個抽象類,並“當場”實現其抽象方法。
既然實現了抽象方法,那麼就是一個新的類,只是這個類,沒有命名。
這樣的類,叫做匿名類
在這裏插入圖片描述

package charactor;
   
public abstract class Hero {
    String name; //姓名
    float hp; //血量    
    float armor; //護甲 
    int moveSpeed; //移動速度
   
    public abstract void attack();  
    public static void main(String[] args) {
         
        ADHero adh=new ADHero();
        //通過打印adh,可以看到adh這個對象屬於ADHero類
        adh.attack();
        System.out.println(adh);
          
        Hero h = new Hero(){
            //當場實現attack方法
            public void attack() {
                System.out.println("新的進攻手段");
            }
        };
        h.attack();
        //通過打印h,可以看到h這個對象屬於Hero$1這麼一個系統自動分配的類名
        System.out.println(h);
    }  
}

本地類

本地類可以理解爲有名字的匿名類
內部類與匿名類不一樣的是,內部類必須聲明在成員的位置,即與屬性和方法平等的位置。
本地類和匿名類一樣,直接聲明在代碼塊裏面,可以是主方法,for循環裏等等地方

package charactor;
   
public abstract class Hero {
    String name; //姓名
          
    float hp; //血量
          
    float armor; //護甲
          
    int moveSpeed; //移動速度
      
    public abstract void attack();
      
    public static void main(String[] args) {
          
        //與匿名類的區別在於,本地類有了自定義的類名
        class SomeHero extends Hero{
            public void attack() {
                System.out.println( name+ " 新的進攻手段");
            }
        }
         
        SomeHero h  =new SomeHero();
        h.name ="地卜師";
        h.attack();
    }
     
}

在匿名類中使用外部的局部變量

在匿名類中使用外部的局部變量,外部的局部變量必須修飾爲final

爲什麼要聲明爲final,其機制比較複雜,請參考第二個Hero代碼中的解釋

注:在jdk8中,已經不需要強制修飾成final了,如果沒有寫final,不會報錯,因爲編譯器偷偷的幫你加上了看不見的final

package charactor;
public abstract class Hero {
    public abstract void attack();  
    public static void main(String[] args) {
        //在匿名類中使用外部的局部變量,外部的局部變量必須修飾爲final
        final int damage = 5;
        Hero h = new Hero(){
            public void attack() {
                System.out.printf("新的進攻手段,造成%d點傷害",damage );
            }
        };
    }
}
package charactor;
   public abstract class Hero {
    public abstract void attack();     
    public static void main(String[] args) {
        //在匿名類中使用外部的局部變量damage 必須修飾爲final
        int damage = 5;
        //這裏使用本地類AnonymousHero來模擬匿名類的隱藏屬性機制      
        //事實上的匿名類,會在匿名類裏聲明一個damage屬性,並且使用構造方法初始化該屬性的值
        //在attack中使用的damage,真正使用的是這個內部damage,而非外部damage 
        //假設外部屬性不需要聲明爲final
        //那麼在attack中修改damage的值,就會被暗示爲修改了外部變量damage的值
        //但是他們倆是不同的變量,是不可能修改外部變量damage的
        //所以爲了避免產生誤導,外部的damage必須聲明爲final,"看上去"就不能修改了
        class AnonymousHero extends Hero{
            int damage;
            public AnonymousHero(int damage){
                this.damage = damage;
            }
            public void attack() {
                damage = 10;
                System.out.printf("新的進攻手段,造成%d點傷害",this.damage );
            }
        }      
        Hero h = new AnonymousHero(damage);      
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章