简体   繁体   English

Java-在具有类的泛型类上使用newInstance() <? extends myClass> :InstantiationException

[英]Java - using newInstance() on a Generic Class with Class<? extends myClass>: InstantiationException

I'm experiment with Generic Classes, and I've run into a hurdle which I cannot overcome. 我正在尝试泛型类,但遇到了我无法克服的障碍。 In short, I'm encountering an error which I do not understand why it is being thrown: InstantiationException 简而言之,我遇到一个错误,我不明白为什么会抛出该错误:InstantiationException

In the documentation it defines this exception as: 在文档中,它将此异常定义为:

Thrown when an application tries to create an instance of a class using the newInstance method in class Class, but the specified class object cannot be instantiated because it is an interface or is an abstract class. 当应用程序尝试使用Class类中的newInstance方法创建类的实例时抛出,但是指定的类对象由于是接口或抽象类而无法实例化。

Now the problem that has me scratching my head is that I do not use the abstract or interface keyword. 现在,让我挠头的问题是我不使用abstract或interface关键字。 I've also heard that it could be due to not having a default constructor (which I have). 我还听说这可能是由于没有默认构造函数(我拥有)造成的。 Just to be sure, I reduced my code to the minimal possible, but still gives an error: 可以肯定的是,我将代码减少到最小,但仍然出现错误:

package Sandbox;

public class Sandbox {


    public static void main(String[] args) {
        Sandbox box = new Sandbox();
    }

    public Sandbox() {
        aMethod(subThread.class);
    }

    public void aMethod(Class<? extends superThread> type) {
        try {

            System.out.println("isInterface: "+type.isInterface());
            System.out.println("isAssignableFrom of subThread: "+type.isAssignableFrom(subThread.class));

            superThread t = type.newInstance();

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private class superThread { // implements Runnable {

        public superThread() {}

        public void run() {}
    }

    private class subThread extends superThread {

        public subThread() {
            super();
        }

        public void run() {
            // more stuff
        }
    }
}

The Output: 输出:

isInterface: false
isAssignableFrom of subThread: true
java.lang.InstantiationException: Sandbox.Sandbox$subThread
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at Sandbox.Sandbox.aMethod(Sandbox.java:20)
    at Sandbox.Sandbox.<init>(Sandbox.java:11)
    at Sandbox.Sandbox.main(Sandbox.java:7)

I'm sure it's quite simple, but I cannot figure this one out. 我敢肯定这很简单,但是我无法弄清楚这一点。 I've tried several things, but nothing has helped. 我已经尝试了几件事,但是没有任何帮助。 Any and all help is appreciated. 任何和所有帮助表示赞赏。

Thanks, Jon 谢谢,乔恩

It's because your inner classes are private. 这是因为您的内部类是私有的。 Simple fix: 简单修复:

public static class superThread { // implements Runnable {

    public superThread() {}

    public void run() {}
}

public static class subThread extends superThread {

    public subThread() {
        super();
    }

    public void run() {
        // more stuff
    }
}

The reasoning is because Class.newInstance must be able to access the constructor for the class you want to create. 原因是因为Class.newInstance必须能够访问要创建的类的构造函数。

Since the class is private, it's not accessible. 由于该类是私有的,因此无法访问。 Also, in order to access a non-static inner class, you essentially have to have an existing instance of the outer class (Sandbox), which newInstance doesn't have. 另外,为了访问非静态内部类,您实际上必须具有外部类的现有实例(Sandbox),而newInstance没有。 As a result, having either public non-static or private static wouldn't work. 结果,使用公共非静态或私有静态将不起作用。

After zjagannatha pointed to the real problem, I also found a fix to my own code that allows me to keep the methods as non-static... essentially I discovered that even though the constructor had zero parameters, Constructor treated it as if it had one. 在zjagannatha指出了真正的问题之后,我还找到了自己的代码的修复程序,使我可以将方法保持为非静态...本质上,我发现,即使构造函数的参数为​​零, Constructor将其视为具有一。 I got it to list the parameter and found it odd that it needed a Sandbox class (I assume the one I'm currently working in) To allow a non-static class, I would need to change my newInstance code to this: 我让它列出了参数,结果发现它需要一个Sandbox类(我假设我正在使用的是一个类)很奇怪。要允许使用非静态类,我需要将newInstance代码更改为:

type.getConstructor(this.getClass()).newInstance(this);

and this works as well 这也很好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM