Java內(nèi)部類總結(jié)

概念介紹

  • 內(nèi)部類
    在Java中,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類。內(nèi)部類是一種非常有用的特性,因為它允許你把一些邏輯相關(guān)的類組織在一起,并控制位于內(nèi)部的類的可視性。

內(nèi)部類分類

廣泛意義上的內(nèi)部類一般分為以下幾種類型:

  • 成員內(nèi)部類
    最普通的內(nèi)部類,它定義在另一個類的內(nèi)部,如下所示
//外部類
class Out {
  private int age = 12;
   
  //內(nèi)部類
  class In {
      public void print() {
          System.out.println(age);
      }
  }
}

public class NormalInnerClass {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
        //或者采用下種方式訪問
        /*
        Out out = new Out();
        Out.In in = out.new In();
        in.print();
        */
    }
}

  • 局部內(nèi)部類
    局部內(nèi)部類是定義在一個方法或者一個作用域里面的類,它和成員內(nèi)部類的區(qū)別在于局部內(nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi)。
interface extendInnerClass{
    public int setAge();
}

//外部類
class Out {
  private int age = 12;
   
  public extendInnerClass getInnerClass(){
      // 局部內(nèi)部類
      class innerClass implements extendInnerClass{
          public int setAge(){
              age++;
              return age;
          }
          
      }
      return new innerClass();
  }
}

public class NormalInnerClass {
    public static void main(String[] args) {
        Out out = new Out();
        System.out.println(out.getInnerClass().setAge());
    }
}

注意,局部內(nèi)部類就像是方法里面的一個局部變量一樣,是不能有public、protected、private以及static修飾符的。

  • 靜態(tài)內(nèi)部類
class Out3 {
    private static int age = 12;
     
    static class In {
        public void print() {
            System.out.println(age);
        }
    }
}

public class staticInnerClass {
    public static void main(String[] args) {
        Out3.In in = new Out3.In();
        in.print();
    }
}

可以看到,如果用static 將內(nèi)部內(nèi)靜態(tài)化,那么內(nèi)部類就只能訪問外部類的靜態(tài)成員變量,具有局限性

其次,因為內(nèi)部類被靜態(tài)化,因此Out.In可以當做一個整體看,可以直接new 出內(nèi)部類的對象(通過類名訪問static,生不生成外部類對象都沒關(guān)系)

  • 匿名內(nèi)部類
interface anonymous{
    public void getAnonymousAge();
}

class Out4 {
    private static int age = 12;
     
    public anonymous getAnonymous(){
        return new anonymous(){

            @Override
            public void getAnonymousAge() {
                System.out.println(age);
            }
        };
    }
}

public class anonymousInnerClass {
    
    public static void main(String[] args) {
        Out4 out = new Out4();
        out.getAnonymous().getAnonymousAge();
    }
        
}

匿名內(nèi)部類是唯一一種沒有構(gòu)造器的類。正因為其沒有構(gòu)造器,所以匿名內(nèi)部類的使用范圍非常有限,大部分匿名內(nèi)部類用于接口回調(diào)。匿名內(nèi)部類在編譯的時候由系統(tǒng)自動起名為Outter$1.class。一般來說,匿名內(nèi)部類用于繼承其他類或是實現(xiàn)接口,并不需要增加額外的方法,只是對繼承方法的實現(xiàn)或是重寫。

深入理解內(nèi)部類

  1. 為什么成員內(nèi)部類可以無條件訪問外部類的成員?
    編譯器會默認為成員內(nèi)部類添加了一個指向外部類對象的引用,那么這個引用是如何賦初值的呢?
    雖然我們在定義的內(nèi)部類的構(gòu)造器是無參構(gòu)造器,編譯器還是會默認添加一個參數(shù),該參數(shù)的類型為指向外部類對象的一個引用,所以成員內(nèi)部類中的Outter this&0 指針便指向了外部類對象,因此可以在成員內(nèi)部類中隨意訪問外部類的成員。從這里也間接說明了成員內(nèi)部類是依賴于外部類的,如果沒有創(chuàng)建外部類的對象,則無法對Outter this&0引用進行初始化賦值,也就無法創(chuàng)建成員內(nèi)部類的對象了。

  2. 為什么局部內(nèi)部類和匿名內(nèi)部類只能訪問局部final變量?
    示例代碼:

public class Test {
    public static void main(String[] args)  {
         
    }
     
    public void test(final int a) {
        new Thread(){
            public void run() {
                System.out.println(a);
            };
        }.start();
    }
}

如果局部變量的值在編譯期間就可以確定,則直接在匿名內(nèi)部里面創(chuàng)建一個拷貝。如果局部變量的值無法在編譯期間確定,則通過構(gòu)造器傳參的方式來對拷貝進行初始化賦值。
為了解決數(shù)據(jù)不一致性問題,java編譯器就限定必須將變量a限制為final變量,不允許對變量a進行更改(對于引用類型的變量,是不允許指向新的對象),這樣數(shù)據(jù)不一致性的問題就得以解決了。

  1. 靜態(tài)內(nèi)部類有特殊的地方嗎?
    從前面可以知道,靜態(tài)內(nèi)部類是不依賴于外部類的,也就說可以在不創(chuàng)建外部類對象的情況下創(chuàng)建內(nèi)部類的對象。另外,靜態(tài)內(nèi)部類是不持有指向外部類對象的引用的,這個讀者可以自己嘗試反編譯class文件看一下就知道了,是沒有Outter this&0引用的。

??贾R點

  1. Static Nested Class 和 Inner Class的不同?
    在方法外部定義的內(nèi)部類前面可以加上static關(guān)鍵字,從而成為Static Nested Class,它不再具有內(nèi)部類的特性,所有,從狹義上講,它不是內(nèi)部類。Static Nested Class與普通類在運行時的行為和功能上沒有什么區(qū)別,只是在編程引用時的語法上有一些差別,它可以定義成public、protected、默認的、private等多種類型,而普通類只能定義成public和默認的這兩種類型。在外面引用Static Nested Class類的名稱為“外部類名.內(nèi)部類名”。在外面不需要創(chuàng)建外部類的實例對象,就可以直接創(chuàng)建Static Nested Class,例如,假設(shè)Inner是定義在Outer類中的Static Nested Class,那么可以使用如下語句創(chuàng)建Inner類:
    Outer.Inner inner = new Outer.Inner();
    由于static Nested Class不依賴于外部類的實例對象,所以,static Nested Class能訪問外部類的非static成員變量。當在外部類中訪問Static Nested Class時,可以直接使用Static Nested Class的名字,而不需要加上外部類的名字了,在Static Nested Class中也可以直接引用外部類的static的成員變量,不需要加上外部類的名字。
    在靜態(tài)方法中定義的內(nèi)部類也是Static Nested Class,這時候不能在類前面加static關(guān)鍵字,靜態(tài)方法中的Static Nested Class與普通方法中的內(nèi)部類的應(yīng)用方式很相似,它除了可以直接訪問外部類中的static的成員變量,還可以訪問靜態(tài)方法中的局部變量,但是,該局部變量前必須加final修飾符。

  2. 內(nèi)部類可以引用它的包含類的成員嗎?有沒有什么限制?
    完全可以。如果不是靜態(tài)內(nèi)部類,那沒有什么限制!
    如果你把靜態(tài)嵌套類當作內(nèi)部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變量,而只能訪問外部類中的靜態(tài)成員,例如,下面的代碼:

class Outer  {  
   static int x;  
   static class Inner  {  
      void test() {  
               syso(x);  
      }  
   }  
}  

參考文獻

[1]java中的內(nèi)部類總結(jié)
[2]Java中為什么要使用內(nèi)部類
[3]Java內(nèi)部類詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java 內(nèi)部類 分四種:成員內(nèi)部類、局部內(nèi)部類、靜態(tài)內(nèi)部類和匿名內(nèi)部類。 1、成員內(nèi)部類: 即作為外部類的一個成...
    ikaroskun閱讀 1,362評論 0 13
  • 一、內(nèi)部類有幾種? 內(nèi)部類分為成員內(nèi)部類、靜態(tài)嵌套類、方法內(nèi)部類、匿名內(nèi)部類。幾種內(nèi)部類的共性:A、內(nèi)部類仍然是一...
    yekai閱讀 348評論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,854評論 18 399
  • 這里是簡書早報,每天匯集當日好文,宜配合早午餐一起食用~點擊標題查看完整文章,點擊作者名字關(guān)注后可收集作者更多動態(tài)...
    簡黛玉閱讀 8,928評論 9 88
  • 讀《春江花月夜》之時,一派心馳神往,腦海中浮現(xiàn)著那月下的芳甸華林景象。宛如一幅淡雅的中國水墨畫,美得不忍猝讀。 ...
    雁南回閱讀 606評論 4 3

友情鏈接更多精彩內(nèi)容