15

我似乎不能getConstructor用于没有参数的构造函数。

我不断收到以下异常:

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

这是代码:

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();打印"konstruktor"没有问题。

4

5 回答 5

27

当您阅读以下javadoc 时,问题就很清楚了.getConstructor()

返回一个 Constructor 对象,该对象反映此 Class 对象表示的类的指定公共构造函数。

强调我的。

在您的代码中,构造函数不是公开的!

例子:

// 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();
    }
}

指向 SO 答案的强制性链接,该答案也提供了 JLS 参考。特别要注意,默认构造函数与类具有相同的访问修饰符。

于 2014-12-20T12:01:33.423 回答
2

似乎您的类提供了一个不是默认构造函数的构造函数。不带参数调用 getConstructor() 需要类具有默认构造函数。下面的测试说明了这一点。

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();
    }
}

因此,一种可能的解决方案是更改对 getConstructor() 的调用以包含正确的类型,或者在对象本身上提供默认构造函数(但为什么要这样做呢?)。

于 2014-12-20T12:00:22.087 回答
1

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

似乎Class和Constructor类都有newInstance方法,区别在于Class类中只能调用不带参数的newInstance,所以被调用的构造器必须是无参数的(当你有多个时这也会带来问题)构造函数)。Constructor 类中的方法 newInstance 还允许您使用参数调用构造函数,请注意,您还可以使用 getConstructors 方法而不是 getConstructor 方法,它返回所有类构造函数并允许您调用所需的构造函数方法。

在这种情况下,由于您只有一个构造函数并且没有参数,因此 Class.newInstance 可以正常工作。要使用 getConstructor 获得相同的结果,您需要在最后添加 oCon.newInstance();

于 2014-12-20T12:05:18.910 回答
1

您可以使用getDeclaredConstructors()which 返回一个 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();
        }

    }
}

如果你有这样的私有构造函数:

class SomeClass{

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

}

您必须为构造函数设置可访问性:

constructor.setAccessible(true);

得到这样的东西:

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");
        }

    }
}

注意:如果你的类声明为private他的默认构造函数也必须是private

并且要小心接收外部类实例的非静态内部类

于 2019-11-18T16:34:43.123 回答
0

在这个(有点复杂的)场景中,实际上可以通过替换来获取(非公共)构造函数:

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

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

Jeden类(及其构造函数)的“默认”可见性使类可以访问它Start,因为它是在同一个包中定义的。

于 2020-04-17T17:03:17.407 回答