使用反射的方法,創(chuàng)建一個非靜態(tài)內(nèi)部類的實例

定義一個包含非靜態(tài)內(nèi)部類的類

public class Outer {

  //內(nèi)部類
   public class Inner{
      private String name = "默認(rèn)值";
      public Inner(){
      }

      public Inner(String name){
         this.name = name;
      }

      public String getName() {
         return name;
      }

      public void setName(String name) {
         this.name = name;
      }

      @Override
      public String toString(){
         return "Inner 對象:"+this.name;
      }
   }
}

利用反射的方法獲取內(nèi)部類的實例

import java.lang.reflect.Constructor;

public class Test {

   public static void main(String[] args) throws Exception {
      System.out.println(new Outer().new Inner());

      //使用反射的方法創(chuàng)建
      Class cls = Outer.Inner.class;

      Constructor constructor1 = cls.getDeclaredConstructor(Outer.class);
      Constructor constructor2 = cls.getDeclaredConstructor(Outer.class, String.class);

      Outer.Inner in1 = (Outer.Inner) constructor1.newInstance(new Outer());
      Outer.Inner in2 = (Outer.Inner) constructor2.newInstance(new Outer(), "測試");


      System.out.println(in1);
      System.out.println(in2);
   }
}

在用反射創(chuàng)建內(nèi)部的實例時,為什么會傳入了Outer類的實例,我們明明在內(nèi)部類中,定義了下面兩個構(gòu)造器???

public Inner(){
}

public Inner(String name){
   this.name = name;
}

使用javap工具分析Inner類

javap -c Outer$Inner.class 命令得到如下文件

Compiled from "Outer.java"
public class com.nanc.Outer$Inner {
  final com.nanc.Outer this$0;

  public com.nanc.Outer$Inner(com.nanc.Outer);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:Lcom/nanc/Outer;
       5: aload_0
       6: invokespecial #2                  // Method java/lang/Object."<init>":()V
       9: aload_0
      10: ldc           #3                  // String 默認(rèn)值
      12: putfield      #4                  // Field name:Ljava/lang/String;
      15: return

  public com.nanc.Outer$Inner(com.nanc.Outer, java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:Lcom/nanc/Outer;
       5: aload_0
       6: invokespecial #2                  // Method java/lang/Object."<init>":()V
       9: aload_0
      10: ldc           #3                  // String 默認(rèn)值
      12: putfield      #4                  // Field name:Ljava/lang/String;
      15: aload_0
      16: aload_2
      17: putfield      #4                  // Field name:Ljava/lang/String;
      20: return

  public java.lang.String getName();
    Code:
       0: aload_0
       1: getfield      #4                  // Field name:Ljava/lang/String;
       4: areturn

  public void setName(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #4                  // Field name:Ljava/lang/String;
       5: return

  public java.lang.String toString();
    Code:
       0: new           #5                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #7                  // String Inner 對象:
       9: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: aload_0
      13: getfield      #4                  // Field name:Ljava/lang/String;
      16: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: areturn
}

可以明顯看到,非靜態(tài)內(nèi)部類Inner并沒有無參的構(gòu)造器,它的構(gòu)造器需要一個Outer參數(shù)。

為什么會這樣?

系統(tǒng)在編譯階段總會為非靜態(tài)內(nèi)部類的構(gòu)造器增加一個參數(shù),非靜態(tài)內(nèi)部類的構(gòu)造器的第一個參數(shù)總是外部類。因此調(diào)用非靜態(tài)內(nèi)部類的構(gòu)造器時必須傳入一個外部類對象作為參數(shù),否則程序?qū)l(fā)運行時異常。

非靜態(tài)內(nèi)部類的規(guī)則

非靜態(tài)內(nèi)部類必須寄生在外部類的實例中,沒有外部類的對象,就不可能產(chǎn)生非靜態(tài)內(nèi)部類的對象。因此非靜態(tài)內(nèi)部類不可能有無參的的構(gòu)造器---即使系統(tǒng)為非靜態(tài)內(nèi)部類提供一個默認(rèn)的構(gòu)造器,這個默認(rèn)的的構(gòu)造器也需要一個外部類的形參。

如果要繼承一個非靜態(tài)內(nèi)部類該怎么寫哩

public class Test extends Outer.Inner{

    /**
     * 為什么要這么寫?
     * 因為Inner類沒有無參構(gòu)造器
     * 使用 new Outer()作為主調(diào)----即以一個Out對象作為主調(diào),
     * 其實這個主調(diào)會作為參數(shù)傳入super(),也就是傳給Inner類的帶一個Out參數(shù)的構(gòu)造器。
     */
    public Test(){
        new Outer().super();
    }
}
最后編輯于
?著作權(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,355評論 0 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,706評論 18 399
  • 靜態(tài)對象 靜態(tài)對象的數(shù)據(jù)是全局唯一的,一改全改。 引用方便。直接用 類名. 靜態(tài)方法名 或者 類名 . 靜態(tài)變量名...
    Yanci516閱讀 2,075評論 1 6
  • 世界好! 我是吳艾佳,我現(xiàn)在還是個小不點,像顆紅瓜子那么大,可是我很快就會長大、健康的長大! 爸爸媽媽很喜歡我,她...
    吳艾佳閱讀 304評論 0 0
  • 關(guān)于標(biāo)題 恩,先吐槽下,這個標(biāo)題是在一本計算機著作中引用而來的。當(dāng)然,引用的原因還就是他最為恰當(dāng)。 開發(fā)Garvi...
    文卿閱讀 512評論 0 1

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