getConstructor with no parameters

你离开我真会死。 提交于 2021-02-07 11:35:07

问题


I can't seem to use getConstructor for constructors with no parameters.

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.


回答1:


The problem is clear when you read the javadoc of .getConstructor():

Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.

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. In particular, note that the default constructor has the same access modifier as the class.




回答2:


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. 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?).




回答3:


Read this: 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). 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.

In this case, since you only have one constructor only and with no arguments, Class.newInstance works fine. To use the getConstructor to have the same result you'll need to add in the end oCon.newInstance();




回答4:


You can use getDeclaredConstructors() which returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object

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.

And be careful with nonstatic-inner classes, which receives an outer class instance




回答5:


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.



来源:https://stackoverflow.com/questions/27579783/getconstructor-with-no-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!