天天看點

内部類詳解

内部類詳解

1.成員内部類

1.樣例

class OutClass {
    class InnerClass {
        public String SayHi() {
           return "你好";
        }
    }
}      

2.特點

  1. 内部類能夠無條件的通路外部類的成員變量,外部類要通路内部類成員變量需要使用new。
  2. 内部類和外部類有相同名稱的變量或者是方法,通路外部類方式為:外部類.this.方法。
  3. 内部類是依賴外部類的,隻有先有外部類才能有内部類。調用内部類方法為:
OutClass out = new OutClass();
OutClass.InnerClass inner = out.new InnerClass();      
  1. 内部類的權限可以public,protected,保護類型和private。而外部類隻能是public和保護類型。
  2. 成員内部類不能存在static關鍵字,非靜态内部類也可以定義靜态成員但需要同時有final關鍵詞修飾。

2.局部内部類

public class Outer {
    private int s = 100;
    private int out_i = 1;

    public void f(final int k) {
        final int s = 200;
        int i = 1;
        final int j = 10;

        // 定義在方法内部
        class Inner {
            int s = 300;// 可以定義與外部類同名的變量

            // static int m = 20;//不可以定義靜态變量
            Inner(int k) {
                inner_f(k);
            }
            int inner_i = 100;
            void inner_f(int k) {
                // 如果内部類沒有與外部類同名的變量,在内部類中可以直接通路外部類的執行個體變量
                System.out.println(out_i);
                // 可以通路外部類的局部變量(即方法内的變量),但是變量必須是final的
                System.out.println(j);
                // System.out.println(i);
                // 如果内部類中有與外部類同名的變量,直接用變量名通路的是内部類的變量
                System.out.println(s);
                // 用this.變量名通路的也是内部類變量
                System.out.println(this.s);
                // 用外部類名.this.内部類變量名通路的是外部類變量
                System.out.println(Outer.this.s);
            }
        }
        new Inner(k);
    }

    public static void main(String[] args) {
        // 通路局部内部類必須先有外部類對象
        Outer out = new Outer();
        out.f(3);
    }
}      

是指内部類定義在一個類的方法,代碼塊中。

  1. 局部内部類隻能在代碼代碼塊、方法體内和作用域中使用(如建立對象和使用類對象等)
  2. 局部内部類通路作用域内的局部變量,該局部變量需要使用final修飾。
  3. 可以使用abstract修飾,聲明為抽象類。
  4. 隻能在定義該類的方法中執行個體化。

3.靜态内部類

public class Outer {
    private static int i = 1;
    private int j = 10;
    public static void outer_f1() {}
    public void outer_f2() {}

    // 靜态内部類可以用public,protected,private修飾
    // 靜态内部類中可以定義靜态或者非靜态的成員
    private static class Inner {
        static int inner_i = 100;
        int inner_j = 200;

        static void inner_f1() {
            // 靜态内部類隻能通路外部類的靜态成員(包括靜态變量和靜态方法)
            System.out.println("Outer.i" + i);
            outer_f1();
        }

        void inner_f2() {
            // 靜态内部類不能通路外部類的非靜态成員(包括非靜态變量和非靜态方法)
            // System.out.println("Outer.i"+j);
            // outer_f2();
        }
    }

    public void outer_f3() {
        // 外部類通路内部類的靜态成員:内部類.靜态成員
        System.out.println(Inner.inner_i);
        Inner.inner_f1();
        // 外部類通路内部類的非靜态成員:執行個體化内部類即可
        Inner inner = new Inner();
        inner.inner_f2();
    }

    public static void main(String[] args) {
        new Outer().outer_f3();
    }
}      

使用static修飾的内部類。

  1. 不依賴外部類,不能使用外部類非靜态的變量和方法。
  2. 不需要如成員内部類一樣,生成外部類對象來生成内部類。
  3. 靜态内部類中可以定義靜态或者非靜态的成員。
  4. 外部類通路内部類的靜态成員:内部類.靜态成員。
  5. 外部類通路内部類的非靜态成員:執行個體化内部類即可。
  6. 可以有非靜态的方法或者變量。

3.使用場景

  1. 當外部需要使用内部類而内部類不依賴與外部類的資源。
  2. 能夠單獨生成對象。
  3. 節省資源。

4.匿名内部類

就是沒有名字的内部類。匿名内部類的格式:

new 接口或父類(){
              重寫抽象方法
      };      

2.應用場景

個人了解就是沒有實作一個接口,但是想重寫接口中的方法并且調用并傳回。

目的:

  1. 可以使命名變得簡潔。
  2. 使代碼更加緊湊,簡潔,封裝性比内部類更優。
  3. 一個類用于繼承其他類或是實作接口,無需增加其他的方法,隻是對繼承方法實作 覆寫。
public class OuterClass {
    public InnerClass getInnerClass(final int num,String str2){
        return new InnerClass(){
            int number = num + 3;
            public int getNumber(){
                return number;
            }
        };        /* 分号不能省 */
    }
    
    public static void main(String[] args) {
        OuterClass out = new OuterClass();
        InnerClass inner = out.getInnerClass(2, "chenssy");
        System.out.println(inner.getNumber());
    }
}

interface InnerClass {
    int getNumber();
}

----------------
Output:
5      

如果不适用匿名内部類

interface InnerClass {
    int getNumber(int a);
}

class InnerClassImpl{ 
   int getNumber(int a){
   system.out.print(a);}
}

InnerClass  InnerClass  = new InnerClassImpl();
使用匿名内部類之後
InnerClass  InnerClass =  new InnerClass (){
    public int getNumber(int a){
                return a;
            }
}
      

特點:

  1. 匿名内部類是沒有通路修飾符的。
  2. new 匿名内部類,這個類首先是要存在的。如果我們将那個InnerClass接口注釋掉,就會出現編譯出錯。
  3. 注意getInnerClass()方法的形參,第一個形參是用final修飾的,而第二個卻沒有。同時我們也發現第二個形參在匿名内部類中沒有使用過,是以當所在方法的形參需要被匿名内部類使用,那麼這個形參就必須為final。
  4. 匿名内部類是唯一一種沒有構造方法的類。
  5. 匿名内部類不能定義任何靜态成員、方法和類。

5.使用内部類的原因:

  1. 可以實作多重繼承。(不同的内部類可以繼承不同的類)。
  2. 内部類可以更好的隐藏。
  3. 當我們不想寫接口的實作或隻是用一次對象時可以使用匿名内部類。
  4. 每個内部類都是一個單獨的個體。