是否可以使用 Java 反射创建内部类的实例?

2022-09-01 07:13:48

代码示例:

public class Foo
{
    public class Bar
    {
         public void printMesg(String body)
         {
             System.out.println(body);
         }
    }
    public static void main(String[] args)
    {
         // Creating new instance of 'Bar' using Class.forname - how?
    }        
}

是否可以创建类 Bar 的新实例来命名它?我试图使用:

Class c = Class.forName("Foo$Bar")

它找到类,但是当我使用c.newInstance()时,它会抛出InstantiationException。


答案 1

你需要跳过几个箍来做到这一点。首先,您需要使用 Class.getConstructor() 来查找要调用的对象:Constructor

返回一个构造函数对象,该对象反映此类对象所表示的类的指定公共构造函数。parameterTypes 参数是一个 Class 对象数组,这些对象按声明的顺序标识构造函数的形式参数类型。如果此 Class 对象表示在非静态上下文中声明的内部类,则形式参数类型包括显式封闭实例作为第一个参数。

然后你使用 Constructor.newInstance()

如果构造函数的声明类是非静态上下文中的内部类,则构造函数的第一个参数必须是封闭实例


答案 2

实际上,如果不先构造父类,就无法构造内部类。它不能存在于父类之外。执行反射时,必须传入父类的实例。嵌套类是并且它们可以独立于父类使用,因此在进行反射时也可以使用。static

这是一个SSCCE,它演示了所有的东西。

package mypackage;

import java.lang.reflect.Modifier;

public class Parent {

    public static class Nested {
        public Nested() {
            System.out.println("Nested constructed");
        }
    }

    public class Inner {
        public Inner() {
            System.out.println("Inner constructed");
        }
    }

    public static void main(String... args) throws Exception {
        // Construct nested class the normal way:
        Nested nested = new Nested();

        // Construct inner class the normal way:
        Inner inner = new Parent().new Inner();

        // Construct nested class by reflection:
        Class.forName("mypackage.Parent$Nested").newInstance();

        // Construct inner class by reflection:
        Object parent = Class.forName("mypackage.Parent").newInstance();
        for (Class<?> cls : parent.getClass().getDeclaredClasses()) {
            if (!Modifier.isStatic(cls.getModifiers())) {
                // This is an inner class. Pass the parent class in.
                cls.getDeclaredConstructor(new Class[] { parent.getClass() }).newInstance(new Object[] { parent });
            } else {
                // This is a nested class. You can also use it here as follows:
                cls.getDeclaredConstructor(new Class[] {}).newInstance(new Object[] {});
            }
        }
    }
}

这应该产生

Nested constructed
Inner constructed
Nested constructed
Inner constructed
Nested constructed