1. 程式人生 > 實用技巧 >Java基礎 -- 內部類

Java基礎 -- 內部類

1、內部類

內部類是定義在一個類的內部的類,內部類 不能定義靜態變數和方法。介面內也可以使用內部類,但沒必要

  • 更好的實現隱藏:內部類可以被 private 與 protected 修飾
  • 內部類擁有外部類的所有元素的訪問許可權:可以直接呼叫所有外部類的成員,包括 private 修飾的變數和方法、非靜態變數和方法等
  • 可以間接的實現多重繼承:一個類中可以寫多個內部類,分別繼承不同的類
  • 可以避免實現的介面或繼承的類中有同名的方法
  • 當想要定義一個回撥函式且不想編寫大量程式碼時,使用匿名內部類比較便捷

1.1 內部類區別

1.2 成員內部類

public class Test {
    public int x = 1;
    private static int y = 10;
    String str = "Test";

    public void m1() {
        System.out.println("Test m1");
    }

    private static void m2() {
        System.out.println("Test m2");
    }

    void str() {
        System.out.println("Test str");
    }

    // 成員內部類
    class InnerClass {
        String str = "InnerClass";

        void method() {
            // 外部類成員變數
            System.out.println(x);
            // 外部類靜態變數
            System.out.println(y);
            // 同名變數,優先呼叫內部類變數
            System.out.println(str);
            // 外部類同名變數
            System.out.println(Test.this.str);
            // 外部類方法
            m1();
            // 外部類靜態方法
            m2();
            // 同名方法,優先呼叫內部類方法
            str();
            // 外部類同名方法
            Test.this.str();
        }

        void str() {
            System.out.println("InnerClass str");
        }
    }

    public static void main(String[] args) {
        // 先建立外部類物件
        Test test = new Test();
        // 通過外部類物件建立內部類物件
        Test.InnerClass inner = test.new InnerClass();
        // 呼叫內部類方法
        inner.method();
        // 呼叫內部類成員變數
        System.out.println(inner.str);
    }
}

1.3 靜態內部類

被 static 修飾的成員內部類,不需要依賴於外部類的,可以看做靜態變數,不能直接使用外部類的非靜態變數或方法

public class Test {
    public int x = 1;
    private static int y = 10;
    String str = "Test";

    public void m1() {
        System.out.println("Test m1");
    }

    private static void m2() {
        System.out.println("Test m2");
    }

    void str() {
        System.out.println("Test str");
    }

    static class InnerClass {
        private String str = "InnerClass";
        static int i = 10;

        void method() {
            // 外部類成員變數
            System.out.println(new Test().x);
            // 外部類靜態變數
            System.out.println(y);
            // 同名變數,優先呼叫內部類變數
            System.out.println(str);
            // 外部類同名變數
            System.out.println(new Test().str);
            // 外部類方法
            new Test().m1();
            // 外部類靜態方法
            m2();
            // 同名方法,優先呼叫內部類方法
            str();
            // 外部類同名方法
            new Test().str();
        }

        static void staticMethod() {
            // 同名變數,優先呼叫內部類變數
            System.out.println(new InnerClass().str);
            // 外部類同名變數
            System.out.println(new Test().str);
            // 同名方法,優先呼叫內部類方法
            new InnerClass().str();
            // 外部類同名方法
            new Test().str();
        }

        void str() {
            System.out.println("InnerClass str");
        }
    }

    public static void main(String[] args) {
        // 與成員內部類相比,無需建立外部類物件
        InnerClass inner = new InnerClass();
        // 呼叫內部類方法
        inner.method();
        // 呼叫內部類靜態方法
        InnerClass.staticMethod();
        // 呼叫內部類成員變數
        System.out.println(inner.str);
        // 呼叫內部類靜態成員變數
        System.out.println(InnerClass.i);
    }
}

1.4 區域性內部類

public class Test {
    public int x = 1;
    private static int y = 10;
    String str = "Test";

    public void m1() {
        System.out.println("Test m1");
    }

    private static void m2() {
        System.out.println("Test m2");
    }

    void str() {
        System.out.println("Test str");
    }

    public static void main(String[] args) {
        class InnerClass {
            private String str = "InnerClass";

            void method() {
                // 外部類成員變數
                System.out.println(new Test().x);
                // 外部類靜態變數
                System.out.println(y);
                // 同名變數,優先呼叫內部類變數
                System.out.println(str);
                // 外部類同名變數
                System.out.println(new Test().str);
                // 外部類方法
                new Test().m1();
                // 外部類靜態方法
                m2();
                // 同名方法,優先呼叫內部類方法
                str();
                // 外部類同名方法
                new Test().str();
            }

            void str() {
                System.out.println("InnerClass str");
            }
        }
        // 建立內部類物件
        InnerClass inner = new InnerClass();
        // 呼叫內部類方法
        inner.method();
        // 呼叫內部類成員變數
        System.out.println(inner.str);
    }
}

1.5 匿名內部類

沒有名稱的類,利用父類的建構函式和自身類體構造成一個類,其他地方不能引用,沒有構造器,不能例項化,只能使用一次

public class Test {
    int i = 10;

    One o1 = new One() {
        int i = 1;

        @Override
        void show() {
            System.out.println("o1 show");
        }
    };

    void say() {
        System.out.println("Test say");
    }

    public static void main(String[] args) {
        One o2 = new One() {
            @Override
            void show() {
                System.out.println("o2 show");
            }

            void say() {
                System.out.println("o2 say");
            }
        };
        // 定義在方法體外,則需要建立外部類物件
        Test test = new Test();
        // 呼叫內部類方法,o1重寫後的方法
        test.o1.show(); // o1 show
        // 呼叫內部類成員變數
        System.out.println(test.o1.i);  // 0

        // 定義在方法體內,可以直接使用
        o2.show();	// o2 show
        // 只能呼叫One中包含的方法及變數
        o2.say();   // 編譯錯誤
    }
}

class One {
    int i = 0;
    void show() {
        System.out.println("one show");
    }
}

1.6 小夥汁,你見過內部內部內部內部內部內部類嗎

public class Test {

    class InnerClass {
        class InnerInnerClass {
            class InnerInnerInnerClass {
                class InnerInnerInnerInnerClass {
                    class InnerInnerInnerInnerInnerClass {
                        class InnerInnerInnerInnerInnerInnerClass {
                            void show() {
                                System.out.println("內部內部內部內部內部內部類");
                            }
                        }
                    }
                }
            }
        }
    }


    public static void main(String[] args) {
        Test test = new Test();
        Test.InnerClass.InnerInnerClass.InnerInnerInnerClass.InnerInnerInnerInnerClass.InnerInnerInnerInnerInnerClass.InnerInnerInnerInnerInnerInnerClass inner = test.new InnerClass().new InnerInnerClass().new InnerInnerInnerClass().new InnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerInnerClass();
        inner.show();
    }
}