【问题标题】:newInstance() with inner classes带有内部类的 newInstance()
【发布时间】:2014-10-27 09:02:52
【问题描述】:

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

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的实例中实例化。
  • 所以,我必须这样做 NewTest parent = new NewTest();parent.toRun.getConstructor().newInstance()
  • @NonSecwitter 不,parent.toRun 将不可编译。 Java 在new 上用于创建内部类实例的特殊语法不适用于newInstance,它只是具有任何其他方法调用的语法。
  • javadoc for getConstructor 说:“如果此 Class 对象表示在非静态上下文中声明的内部类,则形式参数类型包括显式封闭实例作为第一个参数。” Simone 的回答使用了这个信息。
  • 啊。我读了,直到现在我才明白。我还在习惯行话:/

标签: java reflection instantiation inner-classes


【解决方案1】:

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

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

如果您需要它们共享某些东西,因此外部类将作为一种“范围”工作,您仍然可以不使用内部类来做到这一点,但通过向它们传递某种上下文。

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

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

【讨论】:

  • 知道了。我想我的大脑已经死了,我现在想不出这个说法。
  • 我需要创建一堆不同的按钮监听器。我只是认为创建一系列内部类并动态选择它们会更整洁。
  • 或者我最好只在自己的文件中包含一堆侦听器类并根据需要调用它们?
  • 内部类的唯一优势是可以访问外部类的字段。这就是为什么它们经常用于监听器之类的东西,因为它们可以“从外部”修改主类的状态,所以它们非常适合回调。如果你不需要这个,那么拥有单独的文件不会有什么坏处。
  • 内部类是否可以工作,这样我就可以创建一个通用的ButtonListener 类,该类可以动态加载HelpButtonListenerSubmitButtonListener 并且仍然可以访问最外面的字段?现在我正在分支(if elseif elseif 等)
【解决方案2】:

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

【讨论】:

  • 为什么投反对票?这个答案基本上是正确的,是让它发挥作用的一种方法。
  • 因为这个问题几乎是问实例化static 和非static 类之间有什么区别,这没有回答。
  • class "one" 根本不访问包含的类,因此它没有理由不应该是静态的
  • 它最终会访问包含的类。我只是想弄清楚动态加载的基础知识。
【解决方案3】:

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

new NewTest().new one()

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

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

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

【讨论】:

  • 我无法理解 .new 在内部是如何工作的
猜你喜欢
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多