简体   繁体   English

没有参数的 getConstructor

[英]getConstructor with no parameters

I can't seem to use getConstructor for constructors with no parameters.我似乎无法将getConstructor用于没有参数的构造函数。

I keep getting the following exception:我不断收到以下异常:

java.lang.NoSuchMethodException: classname.<init>()

Here is the code:这是代码:

interface InfoInterface {
    String getClassName();
    String getMethodName();
    String getArgument();
}

class asa implements InfoInterface {
    @Override
    public String getClassName() {
        return ("jeden");
    }
    @Override
    public String getMethodName() {
        return ("metoda");
    }
    @Override
    public String getArgument() {
        return ("krzyk");
    }
}

class Jeden {
    Jeden() {
        System.out.println("konstruktor");
    }

    public void Metoda(String s) {
        System.out.println(s);
    }
}

class Start {
    public static void main(String[] argv) {
        if (argv.length == 0) {
            System.err.println("Uzycie programu: java Start nazwa_klasy nazwa_klasy2...");
            return;
        }

        try {
            for (int x = 0; x < argv.length; x++) {
                Class<?> c = Class.forName(argv[x]);
                InfoInterface d = (InfoInterface) c.newInstance();
                String klasa = d.getClassName();
                String metoda = d.getMethodName();
                String argument = d.getArgument();

                Class<?> o = Class.forName(klasa);
                // o.newInstance();

                Constructor<?> oCon = o.getConstructor();
                System.out.println("ASD");
                Class<?> p = (Class<?>) oCon.newInstance();
            }
        } catch (Exception e) {
            System.out.println(e);
        }

    }
}

o.newInstance(); prints "konstruktor" without problems.打印"konstruktor"没有问题。

The problem is clear when you read the javadoc of .getConstructor() :当您阅读.getConstructor()javadoc 时,问题.getConstructor()清楚了:

Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数。

Emphasis mine.强调我的。

In your code, the constructor is not public!在您的代码中,构造函数不是公开的!

Example:例子:

// Note: class is NOT public -- its default constructor won't be either
final class Test
{
    public static void main(final String... args)
        throws NoSuchMethodException
    {
        // throws NoSuchMethodException
        Test.class.getConstructor();
    }
}

Obligatory link to an SO answer which also gives the JLS reference. SO 答案的强制性链接,该答案也提供了 JLS 参考。 In particular, note that the default constructor has the same access modifier as the class.特别要注意的是,默认构造函数与类具有相同的访问修饰符。

It seems as if your class provides a constructor that is NOT a default constructor.好像您的类提供了一个不是默认构造函数的构造函数。 The call to getConstructor() without parameters requires the class to have a default constructor.不带参数调用 getConstructor() 要求类具有默认构造函数。 The following test illustrates this.下面的测试说明了这一点。

import org.junit.Test;

public class ConstructorTest {
    public static class ClassWithParameterizedConstructor {
        public ClassWithParameterizedConstructor(final String param) {
            // A parameterized constructor, no default constructor exists
        }
    }

    @Test
    public void testFoo() throws NoSuchMethodException {
        // Parameterized constructor lookup works fine
        ClassWithParameterizedConstructor.class.getConstructor(String.class);

        // This doesn't work since there is no default constructor
        ClassWithParameterizedConstructor.class.getConstructor();
    }
}

So, a possible solution is to either change the call to getConstructor() to include the correct type or to provide a default constructor on the object itself (but why would you do that?).因此,一个可能的解决方案是更改对 getConstructor() 的调用以包含正确的类型或在对象本身上提供默认构造函数(但为什么要这样做?)。

Read this: http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html阅读: http : //docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

It seems that both classes Class and Constructor have the method newInstance the difference is that in the Class class you can only call newInstance with no arguments, so the called constructor must have an no arguments (this also brings a problem when you have more that one constructor).似乎 Class 和 Constructor 类都有 newInstance 方法,区别在于在 Class 类中你只能不带参数调用 newInstance,所以被调用的构造器必须不带参数(这也会带来一个问题,当你有更多的时候构造函数)。 The methoe newInstance in the Constructor class allows you to call the constructor with arguments also, notice that you can also use the method getConstructors instead of getConstructor that returns you all the class constructors and allows you to call the constructor method you want. Constructor 类中的methoe newInstance 也允许您使用参数调用构造函数,请注意,您还可以使用方法 getConstructors 而不是 getConstructor ,它返回所有类构造函数并允许您调用所需的构造函数方法。

In this case, since you only have one constructor only and with no arguments, Class.newInstance works fine.在这种情况下,由于您只有一个构造函数并且没有参数,因此 Class.newInstance 可以正常工作。 To use the getConstructor to have the same result you'll need to add in the end oCon.newInstance();要使用 getConstructor 获得相同的结果,您需要在末尾添加 oCon.newInstance();

You can use getDeclaredConstructors() which returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object您可以使用getDeclaredConstructors()返回一个 Constructor 对象数组,该数组反映了此 Class 对象表示的类声明的所有构造函数

class SomeClass{

    {
        System.out.println("I'am here!");
    }

}

public class Main {
    public static void main(String[] args) throws Exception{

        System.out.println(Arrays.toString(SomeClass.class.getDeclaredConstructors()));
        // returns public, protected, default (package) access, and private constructors

        // System.out.println(SomeClass.class.getConstructor());
        // in that case you got:
        // NoSuchMethodException: reflection.SomeClass.<init>()
        // because SomeClass don't have public constructor

        for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){

            constructor.newInstance();
        }

    }
}

And if you have private constructor like this:如果你有这样的私有构造函数:

class SomeClass{

    private SomeClass(String val){
        System.out.println(val);
    }

}

You have to set accessible for constructor:您必须为构造函数设置可访问:

constructor.setAccessible(true);

And get something like this:得到这样的东西:

class SomeClass{

    private SomeClass(String val){
        System.out.println(val);
    }

}

public class Main {
    public static void main(String[] args) throws Exception{

        for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
            // constructor.newInstance("some arg");    // java.lang.IllegalAccessException
            constructor.setAccessible(true);
            constructor.newInstance("some arg");
        }

    }
}

Note: if your class declared as private his default constructor must be private too.注意:如果你的类声明为private他的默认构造函数也必须是private

And be careful with nonstatic-inner classes, which receives an outer class instance并注意接收外部类实例的非静态内部类

In this (somewhat convoluted) scenario, it's actually possible to get hold of the (non-public) constructor by replacing:在这种(有点复杂)的情况下,实际上可以通过替换来获取(非公共)构造函数:

Constructor<?> oCon = o.getConstructor();

with

Constructor<?> oCon = o.getDeclaredConstructor();

The "default" visibility of the Jeden class (and its constructor) makes it accessible to the Start class, since it's defined in the same package. Jeden类(及其构造函数)的“默认”可见性使其可被Start类访问,因为它是在同一个包中定义的。

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

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