1. 程式人生 > >java 內部類簡單介紹

java 內部類簡單介紹

很多人對java的內部類太清楚,今天我們來講解一下java的內部類。總的來說,java的內部類分4種:常規內部類、靜態內部類、區域性內部類、匿名內部類。下面我們來仔細講解一下這幾種類。

內部類定義

什麼是內部類

我們來下個定義:一個類定義在另一個類裡面或者一個方法裡面,這樣的類成為內部類。

內部類作用:

1. 內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許同一個包中的其他類訪問該類
2. 內部類的方法可以直接訪問外部類的所有資料,包括私有的資料
3. 內部類所實現的功能使用外部類同樣可以實現,只是有時使用內部類更方便

常規內部類

這是最普通的一種內部類,它的定義為位於另一個類的內部,形如下面的形式:

public class OutOb {
    private  String outName = "外部類";
    public class InOb{
        private String inName = "內部類";

    }
}

這樣看起來,類InOb像是類OutOb的一個成員,OutOb稱為外部類。

注意:

1.成員內部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態成員)。例如:
/**
* @author 作者 YYD
* @version 建立時間:2016年9月19日 下午7:54:38
* @function 未新增
*/
public class OutOb {
private String outName = “外部類”;

public static String outStaticName ="外部類靜態變數";

public class InOb{

    public void getOutName(){
        System.out.println("這是外部類的OutName:"+outName);
        System.out.println("這是外部類的outStaticName:"+outStaticName);
    }
}

}

2.當成員內部類擁有和外部類同名的成員變數或者方法時,會發生隱藏現象(即預設情況下訪問的是成員內部類的成員。)如果要訪問外部類的同名成員,需要以下面的形式進行訪問:

外部類.this.成員變數
外部類.this.成員方法       

例如:

public class OutOb {

    private  String inName = "外部類同名變數";

    public class InOb{
        private String inName = "內部類";
        public void getInName(){
            System.out.println("這是內部類的InName:"+inName);
            System.out.println("這是外部類的同名:"+OutOb.this.inName);//這是呼叫與內部類重名的外部類屬性

        }
        //方法測試
        public void getOutfun(){
            getOutName();//這是呼叫內部類方法
            OutOb.this.getOutName();//這是呼叫與內部類重名的外部類方法
        }
        public void getOutName(){
            System.out.println("這是和外部類同名的方法");
        }
    }

}

3.雖然成員內部類可以無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這麼隨心所欲了。在外部類中如果要訪問成員內部類的成員,必須先建立一個成員內部類的物件,再通過指向這個物件的引用來訪問:
public class OutOb {

    public void getInData(){
        InOb inOb = new InOb();
        inOb.getInName();
    }
    public class InOb{
        private String inName = "內部類";
        public void getInName(){
            System.out.println("這是內部類的InName:"+inName);
        }
    }
}

4.成員內部類是依附外部類而存在的,也就是說,如果要建立成員內部類的物件,前提是必須存在一個外部類的物件。建立成員內部類物件的一般方式如下:

public class OutOb {
    private  String outName = "外部類";
    public void getOutName(){
        System.out.println(outName);

    }
    public InOb getInObInstance(){
        return new InOb();
    }
    public class InOb{
        private String inName = "內部類";
        public void getInName(){
            System.out.println("這是內部類的InName:"+inName);
        }
    }

    public static void main(String args[]) {
        //方法1
        OutOb outOb  = new OutOb();
        OutOb.InOb inOb1  = outOb.new InOb();
        inOb1.getInName();
        //方法2
        OutOb.InOb inOb12 = outOb.getInObInstance();
        inOb2.getInName();
    }
}

5.內部類可以擁有private訪問許可權、protected訪問許可權、public訪問許可權及包訪問許可權。

情況1如果成員內部類用private修飾,則只能在外部類的內部訪問,因為內部類相當於外部類的一個成員,因此內部類可以只有訪問外部類的成員變數,無論是否是private。
情況2如果用public修飾,則任何地方都能訪問;
情況3如果用protected修飾,則只能在同一個包下或者繼承外部類的情況下訪問;
情況4如果是預設訪問許可權,則只能在同一個包下訪問。這一點和外部類有一點不一樣,外部類只能被public和包訪問兩種許可權修飾。我個人是這麼理解的,由於成員內部類看起來像是外部類的一個成員,所以可以像類的成員一樣擁有多種許可權修飾。

區域性內部類

區域性內部類是定義在一個方法或者一個作用域裡面的類,它和成員內部類的區別在於區域性內部類的訪問僅限於方法內或者該作用域內。
public class OutOb {
private String outName = “外部類”;
public void getInData(){
class InOb{
private String inName = “區域性內部類”;
public void getInName(){
System.out.println(“這是區域性內部類的InName:”+inName);

            }
        }
        InOb inOb  =  new InOb();
        inOb.getInName();
    }
}

注意 區域性內部類就像是方法裡面的一個區域性變數一樣,是不能有public、protected、private以及static修飾符的。

匿名內部類

匿名內部類應該是平時我們編寫程式碼時用得最多的,在編寫事件監聽的程式碼時使用匿名內部類不但方便,而且使程式碼更加容易維護。下面這段程式碼是一段Android事件監聽程式碼:

scan_bt.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }
    });

這段程式碼為兩個按鈕設定監聽器,這裡面就使用了匿名內部類。如下程式碼就是匿名內部類的使用:

 new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub              
        }
    }    

程式碼中需要給按鈕設定監聽器物件,使用匿名內部類能夠在實現父類或者介面中的方法情況下同時產生一個相應的物件,但是前提是這個父類或者介面必須先存在才能這樣使用。當然像下面這種寫法也是可以的,跟上面使用匿名內部類達到效果相同:

private void setListener(){
    scan_bt.setOnClickListener(new Listener1());       
}

class Listener1 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub       
    }
}

注意 這種寫法雖然能達到一樣的效果,但是既冗長又難以維護,所以一般使用匿名內部類的方法來編寫事件監聽程式碼。同樣的,匿名內部類也是不能有訪問修飾符和static修飾符的。

匿名內部類是唯一一種沒有構造器的類。正因為其沒有構造器,所以匿名內部類的使用範圍非常有限,大部分匿名內部類用於介面回撥。匿名內部類在編譯的時候由系統自動起名為Outter$1.class。一般來說,匿名內部類用於繼承其他類或是實現介面,並不需要增加額外的方法,只是對繼承方法的實現或是重寫。

靜態內部類

靜態內部類也是定義在另一個類裡面的類,只不過在類的前面多了一個關鍵字static。靜態內部類是不需要依賴於外部類的,這點和類的靜態成員屬性有點類似,並且它不能使用外部類的非static成員變數或者方法,這點很好理解,因為在沒有外部類的物件的情況下,可以建立靜態內部類的物件,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附於具體的物件。例如:
public class OutOb {
private String outName = “外部類”;

    public static class InOb{
        private String inName = "區域性內部類";
        public void getInName(){
            System.out.println("這是區域性內部類的InName:"+inName);
        }
    }

    public static void main(String args[]) {
        OutOb.InOb outOb  = new OutOb.InOb();
        outOb.getInName();
    }
}

結尾

好了就講到這裡吧,希望對大家有所幫助