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

概念介紹

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

內(nèi)部類分類

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

  • 成員內(nèi)部類
    最普通的內(nèi)部類,它定義在另一個(gè)類的內(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();
        //或者采用下種方式訪問(wèn)
        /*
        Out out = new Out();
        Out.In in = out.new In();
        in.print();
        */
    }
}

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

//外部類
class Out {
  private int age = 12;
   
  public extendInnerClass getInnerClass(){
      // 局部?jī)?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());
    }
}

注意,局部?jī)?nèi)部類就像是方法里面的一個(gè)局部變量一樣,是不能有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)部?jī)?nèi)靜態(tài)化,那么內(nèi)部類就只能訪問(wèn)外部類的靜態(tài)成員變量,具有局限性

其次,因?yàn)閮?nèi)部類被靜態(tài)化,因此Out.In可以當(dāng)做一個(gè)整體看,可以直接new 出內(nèi)部類的對(duì)象(通過(guò)類名訪問(wèn)static,生不生成外部類對(duì)象都沒(méi)關(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)部類是唯一一種沒(méi)有構(gòu)造器的類。正因?yàn)槠錄](méi)有構(gòu)造器,所以匿名內(nèi)部類的使用范圍非常有限,大部分匿名內(nèi)部類用于接口回調(diào)。匿名內(nèi)部類在編譯的時(shí)候由系統(tǒng)自動(dòng)起名為Outter$1.class。一般來(lái)說(shuō),匿名內(nèi)部類用于繼承其他類或是實(shí)現(xiàn)接口,并不需要增加額外的方法,只是對(duì)繼承方法的實(shí)現(xiàn)或是重寫(xiě)。

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

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

  2. 為什么局部?jī)?nèi)部類和匿名內(nèi)部類只能訪問(wèn)局部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è)拷貝。如果局部變量的值無(wú)法在編譯期間確定,則通過(guò)構(gòu)造器傳參的方式來(lái)對(duì)拷貝進(jìn)行初始化賦值。
為了解決數(shù)據(jù)不一致性問(wèn)題,java編譯器就限定必須將變量a限制為final變量,不允許對(duì)變量a進(jìn)行更改(對(duì)于引用類型的變量,是不允許指向新的對(duì)象),這樣數(shù)據(jù)不一致性的問(wèn)題就得以解決了。

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

常考知識(shí)點(diǎn)

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

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

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

參考文獻(xiàn)

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

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

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

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

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