Вы также должны указать полное имя пакета. например: com.bla.TestActivity в качестве аргумента для Class.forName
Ричи,
1
Можете еще что-нибудь получить Class<? extends SomeClass>?
Gobliins
@Gobliins Нет - компилятор не может гарантировать, какой класс вы собираетесь получить, поэтому он дает вам Class <?>. Если вы знаете, какой класс вы собираетесь получить, вам придется его преобразовать (даже если вы все равно получаете предупреждения о непроверенном приведении, потому что приведение небезопасно).
Dylanthepiguy
1
@Gobliins Посмотрите мой ответ о том, как получить подкласс определенного типа.
raphinesse 05
7
Вы можете использовать Class::forNameдля получения объекта класса неизвестного типа. Если вы хотите получить типизированный класс, вы можете использовать Class::asSubclassкласс, возвращаемый Class::forName:
Обычно SO ответить подобным образом - это отредактировать свой ответ. Хотя, поскольку в Java множество исключений (и ваш код просто игнорирует их), комментария будет достаточно, чтобы их решить.
tsn
7
@crazyhatfish - Похоже, Патрик не имел привилегии делать что-нибудь полезное, кроме публикации собственного ответа.
amess
4
@amess Ой, вы правы, я забыл, что для комментариев нужна репутация. Спасибо, что поправили меня.
tsn
2
У меня также было аналогичное требование, у меня был json, исходящий из бэкэнда, который содержит экран и отображение активности. Поскольку json является общим для iOS / Android, мы не могли добавлять такие термины, как Activityв json, поэтому вот что мы сделали
В json для всех Activityили Viewcontrollersиспользуйте простые имена, т.е. for, HomeActivityи HomeViewControllerмы будем использовать "Home" в json.
В приложении мы анализируем json, и я написал следующие служебные методы для динамического получения активности.
Чтобы получить имя класса (т.е. если мы пройдем Home, мы вернемся com.package.HomeActivity)
fun getClassInfoFor(name: String, context: Context):String{
var str = "${context.getPackageName()}.${name}Activity"return str
}
Теперь, чтобы получить класс из строки
try {
val className = Utilties.getClassInfoFor(activityNameFromJSON, context)
val fetchedClass = Class.forName(className)
val showDetailsIntent = Intent(context, fetchedClass)
context.startActivity(showDetailsIntent)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
Таким образом, я могу легко управлять несколькими классами одним и тем же методом. Я использую это в представлении ресайклера, где каждая моя ячейка переходит к другому действию.
Обратите внимание, что ваш ответ на Kotlin;) Может быть, его немного переделать, чтобы он стал Java?
LMD
@LMD, наверное, большинству разработчиков Android, которые ищут ответ, нужна версия на котлине, а не на java;)
Руслан Берозов 08
@RuslanBerozov Оператор пометил вопрос как [java], так что я ожидал бы как минимум версию Java (дополнительный Kotlin, конечно, тоже подойдет).
LMD
@LMD извините, но op опубликовал вопрос в 2012 году. Трудно представить, что он знал о Kotlin в то время. Дело в том, что вопрос также помечен как [android], и в настоящее время я предпочитаю версию Kotlin.
Руслан Берозов
-2
Возможно, это не самый подходящий ответ на ваш вопрос, но, как правило, жестко кодировать литералы имени класса как строки плохо. Может быть лучше использовать
Class<? extends SomeClass>
?Вы можете использовать
Class::forName
для получения объекта класса неизвестного типа. Если вы хотите получить типизированный класс, вы можете использоватьClass::asSubclass
класс, возвращаемыйClass::forName
:Class<? extends Activity> activityClass = Class.forName("com.example.TestActivity") .asSubclass(Activity.class);
Конечно, вам также придется обрабатывать множество разных типов исключений. Как это обычно бывает с отражением.
источник
У Class.forName есть исключения. Это просто дополнение к вышесказанному для решения этой проблемы.
try { t = Class.forName("com.package.classname"); } catch (Exception ignored){}
источник
У меня также было аналогичное требование, у меня был json, исходящий из бэкэнда, который содержит экран и отображение активности. Поскольку json является общим для iOS / Android, мы не могли добавлять такие термины, как
Activity
в json, поэтому вот что мы сделалиВ json для всех
Activity
илиViewcontrollers
используйте простые имена, т.е. for,HomeActivity
иHomeViewController
мы будем использовать "Home" в json.В приложении мы анализируем json, и я написал следующие служебные методы для динамического получения активности.
Чтобы получить имя класса (т.е. если мы пройдем Home, мы вернемся
com.package.HomeActivity
)fun getClassInfoFor(name: String, context: Context):String{ var str = "${context.getPackageName()}.${name}Activity" return str }
Теперь, чтобы получить класс из строки
try { val className = Utilties.getClassInfoFor(activityNameFromJSON, context) val fetchedClass = Class.forName(className) val showDetailsIntent = Intent(context, fetchedClass) context.startActivity(showDetailsIntent) } catch (e: ClassNotFoundException) { e.printStackTrace() }
Таким образом, я могу легко управлять несколькими классами одним и тем же методом. Я использую это в представлении ресайклера, где каждая моя ячейка переходит к другому действию.
источник
Возможно, это не самый подходящий ответ на ваш вопрос, но, как правило, жестко кодировать литералы имени класса как строки плохо. Может быть лучше использовать
синтаксис.
источник