Java非静态方法内局部类反射取构造器报NoSuchMethodException问题咨询
问题根本原因
Java 语言规范中,定义在非静态方法内部的局部类,会隐式持有外部类的实例引用。针对你没有手动声明构造器的TestClass,编译器会自动为它生成一个带参构造器,参数类型就是外部测试类的类型,并不存在你以为的无参构造器,因此调用getDeclaredConstructor()(传入空参数列表匹配无参构造器)时会抛出NoSuchMethodException。
你通过getDeclaredConstructors()拿到的唯一构造器,就是编译器自动生成的这个带外部类实例参数的构造器,你可以打印constructors[0].getParameterCount()验证,它的参数数量是1,参数类型就是你当前测试类的Class对象。
和方法静态属性的关联
- 如果局部类定义在静态方法中:静态方法不关联外部类的实例,因此局部类不需要持有外部类引用,编译器会为没有手动声明构造器的局部类生成真正的无参构造器,所以你在静态的scratch方法中可以正常调用
getDeclaredConstructor()拿到构造器。 - 如果局部类定义在非静态方法中:就会出现前面说的自动追加外部类参数的情况,不存在无参构造器。
解决方案
你可以根据业务场景选择以下任意一种方式处理:
- 匹配自动生成的带参构造器
调用getDeclaredConstructor时传入外部测试类的Class对象即可匹配到对应的构造器,示例代码如下:
public void testMethod() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { class TestClass { } // 此处传入当前测试类的Class对象作为构造器参数匹配条件 Constructor<TestClass> constructor = TestClass.class.getDeclaredConstructor(this.getClass()); // 实例化时需要传入当前测试类的实例this TestClass instance = constructor.newInstance(this); // 后续测试逻辑 }
- 调整类的定义位置
如果不需要在TestClass中访问外部测试类的非静态成员,可以把TestClass从方法内移出,定义为测试类的静态内部类,此时它的默认构造器就是无参的,可以直接通过getDeclaredConstructor()获取。 - 沿用你当前的临时方案
如果不需要显式匹配构造器参数,直接调用getDeclaredConstructors()取数组第一个元素的方式可以正常使用,仅需注意如果手动为TestClass声明了多个构造器时,需要判断参数列表取对应构造器即可。
内容的提问来源于stack exchange,提问作者M. Dudek
相关产品推荐
相关产品推荐

