1. 程式人生 > 實用技巧 >【Java】內部類

【Java】內部類

做題目時經常遇到,始終沒能完全搞清楚,這裡總結一下

內部分類:

  • 成員內部類
  • 靜態內部類
  • 區域性內部類
  • 匿名內部類

成員內部類

  1. 相當於外部類的一個成員變數,可以用任意訪問修飾符
  2. 定義的方法可以直接訪問外部類的資料,不受訪問控制符的影響,比如private
  3. 成員內部類的成員不能宣告為static的
  4. 在外部類的靜態成員使用內部類時,內部類要該為靜態內部類
  5. 編譯上述語句後產生兩個.class檔案:Outer.class,Outer$Inner.class{}
  6. 在內部類裡預設訪問自己的成員變數或方法,要訪問外部類的,用外部類物件.this.name
public class Outer{
    private int age = 18;
    String name = "wang";
    public class Inner{
        String name = "wan";
        //static String name = "wan";//不能使用static修飾成員變數和方法
        public void method(){
            System.out.println(Outer.this.name);//使用外部類成員:外部類名.this.成員
            System.out.println(name);//預設使用內部類的成員
            System.out.println(age);//內部類沒有的話就用外部類的
        }
    }
    public Inner getInnerClass(){
        return new Inner();//外部類要先建立內部類物件才能訪問內部類
    }
    public static void main(String[] args){
        Outer outer = new Outer();
        Inner in = outer.new Inner();//內部類 物件名 = 外部類物件.new 內部類()
        in.method();
    }
}

靜態內部類

  • 只能訪問外部靜態成員
  • 屬於外部類本身,不屬於外部類某個物件

靜態內部類是不需要依賴於外部類的,這點和類的靜態成員屬性有點類似,並且它不能使用外部類的非static成員變數或者方法。

class Outter {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
    static class Inner {
        public Inner() {}
    }
}

靜態內部類實現延遲載入單例模式

靜態內部類和成員內部類一樣,都不會因為外部類的載入而載入,在使用時才載入。在載入靜態內部類時也會載入外部類。

public class SingletonIniti {
    private SingletonIniti() {}
    private static class SingletonHolder {
        private static final SingletonIniti INSTANCE = neSingletonIniti();
    }
    public static SingletonIniti getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

區域性內部類

  • 其作用域僅限於方法內,方法外部無法訪問該內部類

  • 不能有public、protected、private 以及 static 修飾符

  • 只能訪問方法中的final的區域性變數,因為方法呼叫完了後就沒了,而區域性內部類還可以存在

    在內部類中的屬性和外部方法的引數兩者從外表上看是同一個東西,但實際上卻不是,所以他們兩者是可以任意變化的, 也就是說在內部類中我對屬性的改變並不會影響到外部的形參,而然這從程式設計師的角度來看這是不可行的,畢竟站在程式的角度來看這兩個根本就是同一個,如果內部類該變了,而外部方法的形參卻沒有改變這是難以理解和不可接受的,所以為了保持引數的一致性,就規定使用 final 來避免形參的不改變

    注意:在JDK8版本之中,方法內部類中呼叫方法中的區域性變數,可以不需要修飾為 final,匿名內部類也是一樣的,主要是JDK8之後增加了 Effectively final 功能

    反編譯jdk8編譯之後的class檔案,發現內部類引用外部的區域性變數都是 final 修飾的

    public class Outer{
        public void Show(){
            final int a = 25;
            int b = 13;
            class Inner{
                int c = 2;
                public void print(){
                    System.out.println("訪問外部類:" + a);
                    System.out.println("訪問內部類:" + c);
                }
            }
            Inner i = new Inner();
            i.print();
        }
        public static void main(String[] args){
            Outer o = new Outer();
            o.show();
        }
    }  
    

匿名內部類

new 類/介面{
    //寫了一堆東西;
};
  • 只能訪問區域性final變數(JDK8開始可以不用final,系統預設加了)
  • 不能有構造方法
  • 不能定義任何靜態的成員、方法
  • 只能建立一個例項
  • 必須且只能繼承一個類或者實現一個介面
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();
}