1. 程式人生 > >java內部類(1):java內部類的建立以及對外提供的訪問方式,匿名內部類詳解

java內部類(1):java內部類的建立以及對外提供的訪問方式,匿名內部類詳解

前言

我們在描述事物的時候,事物的內部還有事物,這個內部事物還要訪問外部事物中的內容時。那麼,這個內部事物就可以用內部類來描述。內部類也叫內建類,巢狀類。

正文

一,內部類的形式以及對外訪問的方式

顧名思義,內部類就是一個類巢狀在另一個類中。內部類可以在外部類的成員位置,也可以在外部類的區域性位置,也就是成員函式中。

一般,我們在定義內部類時設定其訪問許可權為私有private,並在外部類中提供訪問它的方法。下面來看例子:

package com.jimmy.basicInnerClass;

class OuterClass{ // 外部類

    private int num = 5
; // 外部類的成員變數 private class InnerClass{ // 私有的內部類,定義在外部類的成員位置 public void innerMethod() { // 內部類的成員方法 System.out.println("你好啊,我是內部類的方法.."+num); // 內部類可直接訪問外部類的成員 } } public void outerMethos() { // 外部類方法,例項化內部類物件,並呼叫其方法 OuterClass.InnerClass innerClass = new
OuterClass.InnerClass(); innerClass.innerMethod(); } } public class InnerClassDemo1 { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); outerClass.outerMethos(); // 通過外部類方法訪問內部類成員,就像get方法訪問私有成員變數一樣。 } }

上面程式碼的輸出結果:

你好啊,我是內部類的方法..5

值得注意的是,外部類也是一個完整的類,在編譯的時候也有class檔案生成。上面這個檔案就會產生3個class檔案。內部類的名字比較特別,會標明所屬的外部類名。

OuterClass.class
OuterClass$InnerClass.class
InnerClassDemo1.class

上面的程式碼中,我們直接在外部類的方法中建立了內部類物件,並呼叫了內部類的方法,這樣就顯得有點越俎代庖了。我們想自己拿到內部類的物件來呼叫內部類中的方法。但是,內部類是私有的,我們不能直接new出內部類的物件,雖然可以用“new Outer().new Inner()”來例項化內部類物件,但是卻沒有可用的物件名來接收它(因為內部類對外不可見)。怎麼解決呢?我們知道,內部類也是類,同樣具有類的繼承特性,所以我們將內部類繼承自外部的某個類,或者實現外部的某個介面,就可以通過多型來接收內部類物件了,程式碼如下:

package com.jimmy.basicInnerClass;

interface Inter{  // 外部介面
    public void innerMethod();
}

class Outer3{

    private int num = 5;  

    private class Inner implements Inter{  // 內部類實現介面,並實現其中的方法。

        @Override
        public void innerMethod() {
            System.out.println("你好啊,我是內部類的方法...."+num);
        }           
    }

    public Inner getInnerObject() {   // 外部類函式只返回內部類物件,並不越俎代庖去呼叫方法
        return new Inner();
    }

}
public class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer3 outer3 = new Outer3();
        Inter innerObject = outer3.getInnerObject();  // 私有的內部類物件可以用多型性來接收
        innerObject.innerMethod();
    }
}

上述程式碼的輸出結果如下:

你好啊,我是內部類的方法....5

這樣一來,私有化的內部類物件就可以通過多型在外部被持有了,這也符合java中的“面向介面程式設計”的要求。

二,匿名內部類

從上面的程式碼可以看出,內部類在外部類的裡面,並可以實現外部介面,然後實現介面中的方法。有的時候,外部介面中的有些實現只用到一次,也就沒必要特意寫一個類來實現介面,可以使用匿名內部類的形式來實現,匿名內部類在外部類的區域性位置,即方法中。

匿名內部類必須繼承一個父類或者實現一個介面。匿名內部類其實就是一個帶有內容的子類物件,格式為:new 介面/父類(){子類內容}。這個格式比較新穎,一般來說,我們在”new Object();”後會以“;”結束。現在new Object(){}後面跟著的是一對“{}”,表示這是一個子類結構體,介面的實現就在這裡面寫。看個例子:

package com.jimmy.basicInnerClass;

interface InterInner{ // 外部介面以及方法
    void innerMethod1();
    void innerMethod2();
}

class Outer2{

    private int num = 1;

    public void outerMethod(){

        new InterInner() {  // 這就是匿名內部類,大括號裡面是介面的實現
            @Override
            public void innerMethod1() {  // 實現方法1
                System.out.println("你好,我是匿名內部類的方法1..."+num);
            }

            @Override
            public void innerMethod2() {  // 實現方法2
                // TODO Auto-generated method stub
                System.out.println("你好,我是匿名內部類的方法2..."+num+1);
            }
        }.innerMethod1();  // new出物件,就能呼叫函式

    }
}

public class InnerClassDemo4 {
    public static void main(String[] args) {

        Outer2 outer2 = new Outer2();
        outer2.outerMethod();
    }
}

上面程式碼new出匿名內部類的物件後直接呼叫了實現後的方法。程式碼輸出:

你好,我是匿名內部類的方法1...1

我們也可以提供匿名內部類的物件,並在外部呼叫匿名內部類的方法,程式碼如下:

package com.jimmy.basicInnerClass;

interface InterInner2{ // 外部介面以及方法
    void innerMethod1();
    void innerMethod2();
}

class Outer4{

    private int num = 1;

    public InterInner2 outerMethod(){

        InterInner2 inner2 = new InterInner2() {  // 接收匿名內部類物件,大括號裡面是介面的實現
            @Override
            public void innerMethod1() {  // 實現方法1
                System.out.println("你好,我是匿名內部類的方法1..."+num);
            }

            @Override
            public void innerMethod2() {  // 實現方法2
                // TODO Auto-generated method stub
                System.out.println("你好,我是匿名內部類的方法2..."+(num+1));
            }
        };

        return inner2;
    }
}
public class InnerClassDemo4_1 {
    public static void main(String[] args) {
        Outer4 outer4 = new Outer4();
        InterInner2 inner2 = outer4.outerMethod();
        inner2.innerMethod1();
        inner2.innerMethod2();
    }
}

程式碼輸出為:

你好,我是匿名內部類的方法1...1
你好,我是匿名內部類的方法2...2

三,匿名內部類的常見用法

匿名內部類只是對介面的一次實現和呼叫,用完就被回收了。其使用可以像上面那樣,將匿名內部類放在外部類的方法中,在外面呼叫外部類的方法,得到內部類物件進而呼叫內部類的方法。如果內部類不需要訪問外部類的成員變數,就可以直接將其放在main方法中。如下示例:

package com.jimmy.niMingInnerClass;

interface movable{
    public void run();
}

public class NimingInnerClassDemo1 {
    public static void main(String[] args) {

        new movable() { 
            @Override
            public void run() {
                System.out.println("i am running...");
            }
        }.run();
    }
}

輸出結果:

i am running...

實際中使用匿名內部類有很多,常見的就是建立執行緒時使用匿名內部類,如下示例:

package com.jimmy.niming;

public class NiMingNeibuleiTest {
    public static void main(String[] args) {

        new Thread(new Runnable() { // 執行緒1  
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName()+"..."+i);
                }
            }
        }).start();

        new Thread(new Runnable() { // 執行緒2      
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName()+"..."+i);
                }
            }
        }).start();
    }
}

輸出結果:

2個執行緒交替執行

總結

只學會了內部類的形式和對外呼叫方法,以及匿名內部類如何實現簡化程式碼。並不是很理解內部類的好處,以後程式設計學習過程中慢慢體會。