带有内部类的newInstance()

时间:2014-09-03 00:46:12

标签: java reflection instantiation inner-classes

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

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)

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

3 个答案:

答案 0 :(得分:19)

非静态内部类需要外部类的实例才能正常工作。所以,他们不会真的&#34;有一个默认的构造函数,它们总是有一种隐藏参数,他们期望外部类实例。

我不知道你为什么要把它们全部放在一堂课上。如果您这样做只有一个文件,请将它们放在一个包中并放在不同的类中。拥有较少的文件并不能使您的计划更好。

如果您需要它们共享某些内容,那么外部类将作为一种&#34;范围&#34;,您仍然可以在不使用内部类的情况下执行此操作,但通过向它们传递某种类型的上下文

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

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

答案 1 :(得分:3)

如果没有父类的实例,则无法实例化非静态内部类。

new NewTest().new one()

上述调用将成功实例化one

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

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

答案 2 :(得分:0)

您需要将类one设为静态。必须使用包含类的实例来实例化非静态嵌套类。