1. 程式人生 > >Java學習個人備忘錄之內部類

Java學習個人備忘錄之內部類

內部類: 將一個類定義在另一個類的裡面,對裡面那個類就稱為內部類.  
class Outer  
{  
    private int num = 3;  
    class Inner //它想訪問Outer中的num, 如果在外面就需要建立一個物件,然後通過公開的介面訪問,但是現在Outer內部, 就可以直接訪問了.這樣方便  
    {  
        void show()  
        {  
            System.out.println("show run..." + num);  
        }  
    }  
    //如果現在想訪問Inner就需要這樣  
    public void method()  
    {  
        Inner in = new Inner();  
        in.show();  
    }  
    //內部類由於在內部, 相當於定義在了成員的位置上, 所以可以用成員修飾符, 如:  
    //private class Test{}  
    static class Inner  
    {  
        static void function()  
        {  
            System.out.println("function run......"+num);  
        }  
    }  
}

內部類訪問特點:
1. 內部類可以直接訪問外部類中的成員.
2. 外部類要訪問內部類, 必須建立內部類的物件.

一般用於類的設計。

分析事物時, 發現該事物描述中還有事物,而且這個事物還在訪問被描述事物的內容。
這時就把還有的事物定義成內部類來描述。

class InnerClassDemo  
{  
    public static void main(String[] args)  
    {  
        Outer out  = new Outer();  
        out.method();  
        //直接訪問外部類中的內部類中的成員.  
        Outer.Inner in = new Oouter().new Inner();  
        in.show();  
        //如果內部類是靜態, 那就相當於一個外部類了.  
        Outer.Inner in = new Outer.Inner();  
        in.show();  
        //如果內部類是靜態的,成員是靜態的.  
        Outer.Inner.function();  
 
        //如果內部類中定義了靜態成員,該內部類也必須是靜態的.  
  
    }  
}  

細節

class Outer  
{  
    int num = 3;  
    class Inner  
    {  
        int num = 4;  
        void show()  
        {  
            int num = 5;  
            System.out.println(num);//5  
            System.out.println(this.num);//4  
            System.out.println(Outer.this.num);//3  
        }  
    }  
    void method()  
    {  
        new Inner().show();  
    }  
}  

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

為什麼內部類能直接訪問外部類中成員呢?
那是因為內部類持有了外部類的引用-----外部類名.this

內部類可以存放在區域性位置上

class Outer  
{  
    int num = 3;  
    Object method()  
    {  
        final int x = 9;  
        class Inner  
        {  
            void show()  
            {  
                System.out.println("show..."+num);  
            }  
        }  
        Object in = new Inner();  
        return in;//0x0045  
    }  
}  
class InnerClassDemo3  
{  
    public static void main(String[] args)  
    {  
        Outer out = new Outer();  
        Object obj = out.method();//0x0045  
    }  
}

內部類在區域性位置上只能訪問區域性中被final修飾的區域性變數。

匿名內部類, 就是內部類的簡寫格式.
必須有前提:
內部類必須繼承或者實現一個外部類或者介面.

匿名內部類: 其實就是一個匿名子類物件.

格式: new 父類or介面(){子類內容}

abstract class Demo  
{  
    abstract void show();  
}  

class Outer  
{  
    int num = 4;  
    class Inner extends Demo //這是正常情況  
    {  
        void show()  
        {  
            System.out.println("show...."+num);  
        }  
    }  
    public void method()  
    {  
        new Demo()//這個就叫匿名內部類  
        {  
            void show()  
            {  
                System.out.println("show...."+num);  
            }  
        }  
    }  
}

匿名內部類的應用

interface Inter  
{  
    void show1();  
    void show2();  
}  

class Outer  
{  
    public void method()  
    {  
        new Inter()  
        {  
            public void show1()  
            {}  
            public void show2()  
            {}  
        }.show1();  //呼叫了show1的方法, 相當於  new Inner().show1();  
          
        //或者用下面的方法  
        Inter in = new Inter()  
        {  
            public void show1()  
            {}  
            public void show2()  
            {}  
        }  
        in.show1();  
        in.show2();  
    }  
}  

通常的使用場景之一:
當函式引數是介面型別時,而且介面中的方法不超過三個.
可以用匿名內部類作為實際引數進行傳遞.

class InnerClassDemo5  
{  
    public static void main(String[] args)  
    {  
        show(new InterImpl());  
    }  
    public static void show(Inter in)  
    {  
        in.show1();  
        in.show2();  
    }  
}  
class InterImpl implements Inter  
{
}  

物件的初始化過程

class Fu  
{  
    int num = 9;  
    {  
        System.out.println("Fu");  
    }  
  
  
    Fu()  
    {  
        super();  
        //顯示初始化  
        //構造程式碼塊初始化  
        show();  
    }  
    void show()  
    {  
        System.out.println("fu show..."+num); //被覆蓋,執行子類  
    }  
}  
class Zi extends Fu  
{  
    int num = 8;  
    {  
        System.out.println("Zi");  
    }  
    Zi()  
    {  
        super();  
        //顯示初始化  
        //構造程式碼塊初始化  
        show();  
    }  
    void show()  
    {  
        System.out.println("zi show..."+num);  
    }  
}  
  
  
class Inner  
{  
    public static void main(String[] args)  
    {  
        new Zi();  
    }  
}
/*
Fu
zi show...0
Zi
zi show...8
*/