Kotlin / Java generics: когда ожидать исключения IllegalAccessException во время создания экземпляра? - PullRequest
4 голосов
/ 27 мая 2020

Обратите внимание на следующие классы

open class BaseClass

class MyClass private constructor(string: String): BaseClass()

И общую c функцию, которая создает экземпляр:

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. В JavaDo c для Constructor.newInstance() указано:

@ exception IllegalAccessException, если этот объект {@code Constructor} применяет управление доступом к языку Java, а базовый конструктор недоступен.

Частный конструктор соответствует моим ожиданиям о «недоступном конструкторе». Почему в этом примере вместо этого выдается NoSuchMethodException и при каких обстоятельствах он может выдавать IllegalAccessException?

1 Ответ

4 голосов
/ 27 мая 2020

Метод getConstructor попытается выбрать конструктор только из списка конструкторов publi c, частные конструкторы не будут рассматриваться. Поскольку он не может найти совпадение publi c, оно выдает NoSuchMethodException.

IllegalAccessException, с другой стороны, будет выброшено методом newInstance, если вы используете getDeclaredConstructor вместо этого, потому что это конкретный метод выбирает конструктор из всех доступных конструкторов, а не только из publi c, поэтому частный конструктор в вашем примере будет извлечен, хотя и недоступен.

Приведенное ниже вызовет 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...