请考虑以下类(class)
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
。 Constructor.newInstance()
的JavaDoc指出:私有(private)构造函数符合我对“无法访问的构造函数”的期望。为什么此示例改为抛出
NoSuchMethodException
,并且在什么情况下可以抛出IllegalAccessException
? 最佳答案
getConstructor
方法将尝试仅从公共(public)构造函数列表中选择一个构造函数,而不会考虑私有(private)构造函数。由于找不到公共(public)匹配项,因此抛出NoSuchMethodException
。
另一方面,如果您使用IllegalAccessException
,则newInstance
方法将抛出getDeclaredConstructor
,因为此特定方法从所有可用的构造函数中选择了构造函数,而不仅仅是公共(public)的构造函数,因此虽然无法访问,但仍将检索示例中的私有(private)构造函数。
下面将抛出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)