美文网首页
使用反射的方法,创建一个非静态内部类的实例

使用反射的方法,创建一个非静态内部类的实例

作者: 缓慢移动的蜗牛 | 来源:发表于2018-07-04 21:54 被阅读0次

定义一个包含非静态内部类的类

public class Outer {

  //内部类
   public class Inner{
      private String name = "默认值";
      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;
      }
   }
}

利用反射的方法获取内部类的实例

import java.lang.reflect.Constructor;

public class Test {

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

      //使用反射的方法创建
      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);
   }
}

在用反射创建内部的实例时,为什么会传入了Outer类的实例,我们明明在内部类中,定义了下面两个构造器啊?

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 默认值
      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 默认值
      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
}

可以明显看到,非静态内部类Inner并没有无参的构造器,它的构造器需要一个Outer参数。

为什么会这样?

系统在编译阶段总会为非静态内部类的构造器增加一个参数,非静态内部类的构造器的第一个参数总是外部类。因此调用非静态内部类的构造器时必须传入一个外部类对象作为参数,否则程序将会引发运行时异常。

非静态内部类的规则

非静态内部类必须寄生在外部类的实例中,没有外部类的对象,就不可能产生非静态内部类的对象。因此非静态内部类不可能有无参的的构造器---即使系统为非静态内部类提供一个默认的构造器,这个默认的的构造器也需要一个外部类的形参。

如果要继承一个非静态内部类该怎么写哩

public class Test extends Outer.Inner{

    /**
     * 为什么要这么写?
     * 因为Inner类没有无参构造器
     * 使用 new Outer()作为主调----即以一个Out对象作为主调,
     * 其实这个主调会作为参数传入super(),也就是传给Inner类的带一个Out参数的构造器。
     */
    public Test(){
        new Outer().super();
    }
}

相关文章

  • 使用反射的方法,创建一个非静态内部类的实例

    定义一个包含非静态内部类的类 利用反射的方法获取内部类的实例 在用反射创建内部的实例时,为什么会传入了Outer类...

  • Android引起内存泄露的几个地方

    非静态内部类创建静态实例造成的内存泄漏将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Co...

  • Java 内存泄漏场景整理(2)

    非静态内部类的静态实例 非静态内部类会持有外部类实例的引用,如果非静态内部类的实例是静态的,就会间接地长期维持着外...

  • Android线程泄漏场景以及解决办法

    1.非静态内部类的静态实例 非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,就会长期的维持着外部类...

  • 内部类

    非静态内部类不能含有静态变量或静态方法 非静态内部类依托于外部类对象而存在,即是内部类存在于外部类对象实例化之后!...

  • 静态内部类

    非静态内部类: 非静态内部类中不能有静态方法、静态成员变量、静态初始化块。 静态内部类: 如果使用static...

  • java基础

    异常及其分类: 反射机制概念: 内部类分为四种:静态内部类:可以定义静态变量,方法,构造方法,且不依赖于外部类实例...

  • Java学习——内部类

    内部类 一,成员内部类(包括静态内部类和非静态内部类) 非静态内部类可以直接访问外部类的成员,反之则不行 非静态内...

  • 反射破坏单例模式(静态内部类)

    java反射,破坏单例模式 静态内部类 反射实例化单例

  • Handler内存泄漏解决及原因分析(源码向)

    1.使用静态内部类和弱引用 自定义静态内部类继承Handler 因为静态内部类不能访问外部类的非静态方法,所以需要...

网友评论

      本文标题:使用反射的方法,创建一个非静态内部类的实例

      本文链接:https://www.haomeiwen.com/subject/zrwyuftx.html