请考虑以下类
open class BaseClass
class MyClass private constructor(string: String): BaseClass()
还有一个创建实例的泛型函数:
inline fun <reified T : BaseClass, reified A : Any> create(arg: A): T = T::class.java.getConstructor(arg::class.java).newInstance(arg)
以下测试失败:
@Test(expected = IllegalAccessException::class)
fun `should throw an IllegalAccessException`() {
val test: MyClass = create("test")
}
因为实际上抛出了java.lang.NoSuchMethodException
。JavaDoc forConstructor.newInstance()
指出:
@exception 非法访问异常,如果这个 {@code 构造函数} 对象 正在实施 Java 语言访问控制和底层 构造函数不可访问。
私有构造函数符合我对"无法访问的构造函数"的期望。为什么这个例子会抛出一个NoSuchMethodException
,在什么情况下它可以抛出一个IllegalAccessException
?
getConstructor
方法将尝试仅从公共构造函数列表中选择构造函数,不考虑私有构造函数。由于它找不到公共匹配项,因此会抛出NoSuchMethodException
。
另一方面,如果您改用getDeclaredConstructor
,IllegalAccessException
将由newInstance
方法抛出,因为此特定方法从所有可用的构造函数(而不仅仅是公共构造函数(中选取构造函数,因此将检索示例中的私有构造函数,尽管无法访问。
下面会抛出IllegalAccessException
:
T::class.java.getDeclaredConstructor(arg::class.java).newInstance(arg)
如果出于某种原因,您想克服它,您可以使用以下内容:
val ct = T::class.java.getDeclaredConstructor(arg::class.java)
ct.trySetAccessible()
return ct.newInstance(arg)