这里我们将展开讲述Java中如何通过反射机制动态构造一个对象。在开始之前,我们先看看测试类中的构造函数定义。如下图:

通过上图,我们可以看出,类内部有3个不同的构造函数。如果按照性质区分,大体如下:
(1)公有无参构造函数
(2)公有带参构造函数
(3)私有带参构造函数
在常规的程序中,第1、2这两种构造函数,在外部程序是可以访问,也就可以调用。而第3种,私有构造函数,外部程序不可访问,也就不能调用。然而,在反射机制中,我们可以突破语法限制,调用私有构造函数,创建对象。为了能更好说明,我们分开2个main 函数,分别测试常规方式调用和反射方式调用。
常规调用


反射调用

通过上面的代码,大家应该已经看出,如何通过反射创建对象了。概要步骤如下:
(1)通过Class.forName方法,创建目标对象类的Class实例。Class类是一个特殊类,它用于表示JVM运行时类或接口的信息。Class类提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。
(2)然后,通过Class实例中的getDeclaredConstructor方法,获取构造函数。这里值得注意的是,获取构造函数有2个方法:getDeclaredConstructor 和 getConstructor。区别就是,第一个获取的是所定义的构造函数,第二个获取的是公有的构造函数。
(3)最后,通过第(2)步获取的构造函数对象,调用newInstance方法创建一个对象。这里要注意的是,如果调用的是默认的无参构造函数,在第(2)步中,直接通过Class实例对象,就可以调用newInstance方法创建一个对象。
注意:
在反射处理上,私有的构造函数默认是不可访问的。也就是,不可以调用的。但是,可以通过设置访问性参数,改变它的可访问性。示例如下:

最后,我们讲下关于反射机制使用中,可能发生的异常。(在测试代码中,为了代码简洁,没有对异常捕捉处理,只是简单地抛出)
(1)LinkageError - 如果链接失败
(2)ExceptionInInitializerError - 如果此方法引发的初始化失败
(3)ClassNotFoundException - 如果找不到类
(4)IllegalAccessException - 如果类或构造函数不可访问。
(5)InstantiationException - 如果这个类表示抽象类、接口、数组类、基元类型或 void;或者,如果类没有 空参构造函数;或者如果实例化由于其他原因而失败。
(6)SecurityException - 如果存在安全管理器 s,并且调用者的类加载器与当前类的类加载器不同或不是其祖先,并且调用 s.checkPackageAccess() 会拒绝访问此类的包;如果请求被拒绝。
(7)NoSuchMethodException - 如果未找到匹配方法。
(8)IllegalArgumentException - 如果实际参数和形式参数的数量不同;如果对基本类型参数的解包转换失败;或者在可能的解包之后,参数值无法通过方法调用转换为相应形式参数的类型;如果此构造函数属于枚举类型。
(9)InvocationTargetException - 如果底层构造函数引发异常。
另外,如何获取所有的构造函数对象。我们可以按照以下的方式来处理:

本节结束