newInstance() 与内部类

我一直在研究一种实例化方法,该方法将允许我将各种类似的类打包到一个外部类中。然后,我可以通过将每个唯一类类型的名称传递给构造函数来实例化该类型。经过大量的研究和错误,这就是我想到的。我留下了一个错误,以证明我的问题。

import java.lang.reflect.Constructor;

public class NewTest
{   
    public static void main(String[] args)
    {

        try
        {
            Class toRun = Class.forName("NewTest$" + args[0]);
            toRun.getConstructor().newInstance();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            System.out.println(ex.getMessage());
        }

    }

    public NewTest(){}

    private class one //Does not instantiate
    {
        public one()
        {
            System.out.println("Test1");
        }
    }

    private static class two //Instantiates okay
    {
        public two()
        {
            System.out.println("Test2");
        }
    }
}

编译此代码并运行结果输出,正如我所期望的那样。java NewTest twoTest2

运行结果java NewTest one

java.lang.NoSuchMethodException: NewTest$one.<init>()
        at java.lang.Class.getConstructor(Unknown Source)
        at java.lang.Class.getConstructor(Unknown Source)
        at NewTest.main(NewTest.java:12)

我对此感到困惑,因为据我所知,我正确地引用了内部类,外部类应该可以访问内部类,并且我有一个默认的no arg构造函数。


答案 1

非静态内部类需要外部类的实例才能正常工作。因此,它们“实际上”没有默认构造函数,它们总是有一种隐藏参数,它们期望在其中具有外部类实例。

我不知道你为什么想把它们都放在一个班级里。如果您这样做是为了使其只有一个文件,请将它们放在包和单独的类中。拥有更少的文件并不能使您的程序更好。

相反,如果你需要它们来共享一些东西,所以外部类将作为一种“范围”工作,你仍然可以在不使用内部类的情况下做到这一点,而是通过向它们传递某种上下文。

如果你真的真的想实例化内部类,你需要使用隐藏构造函数,将外部类作为参数:

NewTest outer = new NewTest();
Class<?> toRun = Class.forName("NewTest$" + args[0]);
Constructor<?> ctor = toRun.getDeclaredConstructor(NewTest.class);
ctor.newInstance(outer);

答案 2

非静态内部类不能在没有其父类的实例的情况下实例化。

new NewTest().new one()

上面的调用将成功实例化 .one

由于修饰符,您正在在没有外部实例的情况下进行实例化。它是一个静态嵌套类twostatic

查看静态嵌套类和内部类之间的区别:http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html