在Java的反射体系中,Class.getDeclaredConstructor()方法可以获取当前类声明的所有构造函数,包括private、protected、默认访问权限的构造函数,不受访问修饰符的限制,这是它和getConstructor()方法的核心区别,后者只能获取public修饰的构造函数。

方法基本用法
Class.getDeclaredConstructor()方法接收一个可变参数,用于指定构造函数的参数类型列表,返回对应的Constructor<T>对象。如果不存在匹配参数类型的构造函数,会抛出NoSuchMethodException异常。
首先我们定义一个包含非公开构造函数的测试类:
public class User {
private String name;
private int age;
// 私有的构造函数
private User(String name, int age) {
this.name = name;
this.age = age;
}
// 默认访问权限的构造函数
User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
获取非公开构造函数的步骤
1. 获取目标类的Class对象
可以通过类名.class、对象.getClass()或者Class.forName("全类名")的方式获取,这里我们使用类名.class的方式:
// 获取User类的Class对象 Class<User> userClass = User.class;
2. 调用getDeclaredConstructor()获取构造函数
根据要调用的非公开构造函数的参数类型,传入对应的Class对象数组。比如要获取私有构造函数User(String, int),就传入String.class和int.class:
try {
// 获取私有构造函数,参数类型为String和int
Constructor<User> privateConstructor = userClass.getDeclaredConstructor(String.class, int.class);
System.out.println("成功获取私有构造函数:" + privateConstructor);
} catch (NoSuchMethodException e) {
System.out.println("未找到匹配的构造函数");
e.printStackTrace();
}
3. 设置构造函数可访问
因为非公开构造函数默认是不可访问的,直接调用会抛出IllegalAccessException异常,所以需要调用Constructor.setAccessible(true)方法绕过访问权限检查:
// 设置构造函数可访问,绕过private限制 privateConstructor.setAccessible(true);
4. 调用构造函数创建对象
使用Constructor.newInstance(Object... initargs)方法传入构造函数的参数,完成对象创建:
try {
// 传入构造函数的参数,创建User对象
User user = privateConstructor.newInstance("张三", 20);
System.out.println("创建的对象:" + user);
} catch (Exception e) {
e.printStackTrace();
}
调用默认访问权限构造函数示例
对于默认访问权限的构造函数,获取和调用的流程和私有构造函数一致,只是不需要额外处理访问权限吗?不对,默认访问权限的构造函数如果在不同包下访问,同样需要设置setAccessible(true),这里我们在同一个包下测试:
try {
// 获取默认访问权限的构造函数,参数为String
Constructor<User> defaultConstructor = userClass.getDeclaredConstructor(String.class);
// 同一包下可以不设置,但是建议统一设置避免跨包问题
defaultConstructor.setAccessible(true);
User user2 = defaultConstructor.newInstance("李四");
System.out.println("创建的对象:" + user2);
} catch (Exception e) {
e.printStackTrace();
}
常见注意事项
- 参数类型匹配:getDeclaredConstructor()传入的参数类型必须和构造函数的参数类型完全一致,比如构造函数参数是int,不能传入Integer.class,否则会抛出NoSuchMethodException。
- 异常处理:反射调用过程中可能抛出多种异常,包括NoSuchMethodException(无匹配构造函数)、IllegalAccessException(访问权限不足)、InstantiationException(类是抽象类或接口无法实例化)、InvocationTargetException(构造函数内部抛出异常),需要做好异常捕获。
- 访问权限恢复:如果不需要长期保留构造函数的可访问状态,调用完成后可以调用setAccessible(false)恢复默认权限,避免影响其他代码逻辑。
- 性能问题:反射调用的性能比直接调用低,如果不是必要场景,不建议频繁使用反射调用非公开构造函数。
完整示例代码
import java.lang.reflect.Constructor;
public class ReflectConstructorDemo {
public static void main(String[] args) {
Class<User> userClass = User.class;
try {
// 调用私有构造函数
Constructor<User> privateConstructor = userClass.getDeclaredConstructor(String.class, int.class);
privateConstructor.setAccessible(true);
User user1 = privateConstructor.newInstance("张三", 20);
System.out.println(user1);
// 调用默认访问权限构造函数
Constructor<User> defaultConstructor = userClass.getDeclaredConstructor(String.class);
defaultConstructor.setAccessible(true);
User user2 = defaultConstructor.newInstance("李四");
System.out.println(user2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class User {
private String name;
private int age;
private User(String name, int age) {
this.name = name;
this.age = age;
}
User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
Java反射Class.getDeclaredConstructor非公开构造函数Constructor类修改时间:2026-07-08 13:00:36