JAVA的getConstructor方法会抛出NoSuchMethodException异常。

10

我刚学习JAVA,正在尝试学习反射。 我想要从我的类中获取特定构造函数(参考这里的示例):

public class Example1 {
    public Example1() {
    }

    public Example1(int i) {
    }

    public Example1(String s) {
        System.out.println("using param = " + s);
    }

    public static void main(String[] args) throws Exception {  
        Class<?>[] paramTypes = String.class.getClasses();
        Constructor<Example1> ctor = Example1.class.getConstructor(paramTypes);
        ctor.newInstance("test");
    }
}
我尝试实例化ctor时出现了NoSuchMethodException异常。
我在这里漏掉了什么?

3
你的代码实际上没有抛出任何异常。由于在 main() 中没有检查 NoSuchMethodException 和 SecurityException 异常,因此它也无法编译通过。 - tzima
请在您的main()方法中添加throws Exception,并尝试实例化该类(ctor.newInstance("foo"))。这样问题就符合网站的标准了,我会给它点赞(事实上,现在它不能编译/运行)。 - tzima
虽然编辑后的代码现在可以编译通过,但它抛出了IllegalArgumentException异常,而不是你在标题和帖子中所声称的NoSuchMethodException异常(因此对于潜在的寻找NoSuchMethodException解决方案的读者来说仍然不是非常有用)。 - Pshemo
最后再编辑一下 :) 现在它会抛出NoSuchMethodException异常,就像他所提到的那样。由于String.class.getClasses()返回一个空数组,并且实际上存在非参数构造函数,因此找到了它。问题发生在尝试实例化它时(IllegalArgumentException)。我认为现在这对其他人来说应该是可以OK和有帮助的了。 - tzima
我的编辑被拒绝了(投票3:2)。我只是删除了非参数构造函数。现在问题不正确,没有意义,应该被删除,我的答案是浪费时间,所有的编辑也是浪费时间,因此我开始不喜欢这个网站。 - tzima
显示剩余10条评论
2个回答

11

工作示例:

import java.lang.reflect.Constructor;

public class Test {
    public Test(String str) {
        System.out.println(str);
    }

    public Test(int a, int b) {
        System.out.println("Sum is " + (a + b));
    }

    public static void main(String[] args) throws Exception {
        Constructor<Test> constructorStr = Test.class.getConstructor(String.class);
        constructorStr.newInstance("Hello, world!");

        Constructor<Test> constructorInts = Test.class.getConstructor(int.class, int.class);
        constructorInts.newInstance(2, 3);
    }
}

请注意,getConstructor方法实际上并不接受数组作为参数。它的定义如下:

public Constructor<T> getConstructor(Class<?>... parameterTypes) {

这意味着它接受可变数量的参数,这些参数应该像我做的那样传递。传递一个数组也是可能的,但并不必要。

你最初所做的相当于:

    Constructor<Test> constructor = Test.class.getConstructor(String.class.getClasses());
    constructor.newInstance("Hello");

但是,String.class.getClasses() 返回什么呢?好问题!让我们去调试:

    Class<?>[] classes = String.class.getClasses();
    System.out.println(classes.length); // prints 0

有一个有关getClasses()的文档:https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClasses。查看它,你就会明白为什么是这样的。

为了完整起见,在编辑之前的超级原始问题中还包含一个非参数构造函数:

import java.lang.reflect.Constructor;

public class Example1 {
    public Example1() {
    }

    public Example1(String s) {
        System.out.println("using param = " + s);
    }

    public static void main(String[] args) throws Exception {  
        Constructor<Example1> ctor = Example1.class.getConstructor(String.class.getClasses());
        ctor.newInstance("test");
    }
}

这里出现的问题是抛出了IllegalArgumentException异常。这是因为尽管String.class.getClasses()返回一个空数组,但实际上存在一个符合条件的构造函数 - 一个无参数的构造函数!它没有任何参数,String.class.getClasses()返回的数组也不包含任何内容。这意味着成功找到了构造函数,但是当尝试使用ctor.newInstance("test")实例化它时,它失败了,因为找到的构造函数不接受任何参数。


2
这是因为我从public MainCameraRollXML(Context context)中删除了"public"。 - Bob Lissner

-1

使用它试试

Constructor<example1> ctor = examTesting.getConstructor(new Class[]{String.class});

这将返回一个参数类型为String的构造函数。你的方法可能会返回多个值,因此搜索具有多个参数的构造函数,但未找到 -> 抛出NoSuchMethodException异常。

关于getClasses()的更多信息:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getClasses%28%29


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接