我一直在研究一个实例化方法,该方法将允许我将各种类似的类打包到一个外部类中。然后,我可以通过将每个唯一的类类型的名称传递给构造函数来实例化该类型。经过大量的研究和错误,这就是我的想法。我留下了一个错误,用来证明我的问题。
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 two
会得到输出Test2
,正如我所希望的那样。
运行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)
我对此感到困惑,因为据我所知,我正确地引用了内部类,外部类应该可以访问内部类,并且我有一个默认的无参数构造函数。
非静态内部类需要外部类的实例才能正常工作。因此,它们并没有"真正"有一个默认的构造函数,它们总是有一种隐藏的参数,它们期望在其中有一个外部类实例。
我不知道你为什么要把它们都放在一个班里。如果您这样做是为了使它只是一个文件,请将它们放在一个包和单独的类中。文件数量减少并不能使程序变得更好。
如果你需要它们共享一些东西,那么外部类将作为一种"范围"工作,你仍然可以在不使用内部类的情况下这样做,而是通过向它们传递某种上下文。
如果你真的想实例化内部类,你需要使用以外部类为参数的隐藏构造函数:
NewTest outer = new NewTest();
Class<?> toRun = Class.forName("NewTest$" + args[0]);
Constructor<?> ctor = toRun.getDeclaredConstructor(NewTest.class);
ctor.newInstance(outer);
如果没有其父类的实例,就无法实例化非静态内部类。
new NewTest().new one()
上面的调用将成功地实例化一个one
。
由于static
修饰符,您的two
在没有外部实例的情况下被实例化。它是一个静态嵌套类。
查看静态嵌套类和内部类之间的区别:http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
您需要将类one
设置为静态。非静态嵌套类必须使用包含类的实例进行实例化。