Отримання класу за його назвою


81

Якщо у моєму додатку є клас Activity, який називається TestActivity, чи є спосіб отримати його клас за назвою, як у цьому прикладі:

Class<?> c = getClassByName("TestActivity");

Відповіді:


162

використовувати замість forName ..

щось на зразок цього..

 try {
    Class<?> act = Class.forName("com.bla.TestActivity");
 } catch (ClassNotFoundException e) {
        e.printStackTrace();
}

30
Ви також повинні вказати повну назву пакета. наприклад: com.bla.TestActivity як аргумент Class.forName
Річі

1
Ви також можете щось зробити, щоб отримати Class<? extends SomeClass>?
Гобліїнс,

@Gobliins Ні - компілятор не може гарантувати, який клас ви збираєтесь отримати, тому він дає вам клас <?>. Якщо ви знаєте, який клас ви збираєтесь отримати, вам доведеться його кинути (навіть все одно ви отримуєте неперевірені попередження щодо акторського складу, оскільки акторський склад не є безпечним).
Dylanthepiguy

1
@Gobliins Перевірте мою відповідь про те, як отримати підклас певного типу.
raphinesse

7

Ви можете використовувати, Class::forNameщоб отримати об’єкт класу невідомого типу. Якщо ви хочете отримати набраний клас, ви можете використовувати Class::asSubclassдля класу, що повертається Class::forName:

Class<? extends Activity> activityClass = Class.forName("com.example.TestActivity")
                                               .asSubclass(Activity.class);

Звичайно, вам також доведеться обробляти купу різних типів винятків. Як зазвичай, коли йдеться про рефлексію.


6

Class.forName , здається, є винятки на нього. Це лише для розширення вищезазначеного для вирішення цієї проблеми.

try { t = Class.forName("com.package.classname"); } catch (Exception ignored){}

Звичайним способом відповіді на SO є редагування їхньої відповіді. Хоча, оскільки в Java існує безліч винятків (і ваш код просто ігнорує їх), для вирішення проблеми буде достатньо коментаря .
tsn

7
@crazyhatfish - Здається, Патрік, можливо, не мав привілеїв робити щось корисне, крім публікації власної відповіді.
amess

4
@amess На жаль, ваше право, я забуваю, що коментарі потребують повторення. Дякую за виправлення.
tsn

2

У мене також була подібна вимога, у мене був json, що надходить із серверної бази, який містить екран та відображення активності. Оскільки json є загальним для обох iOS / Android, ми не могли додавати такі терміни, як Activityу json, тож саме це ми і зробили

  1. У json для всіх Activityабо Viewcontrollers, використовуйте прості імена, тобто for, HomeActivityі HomeViewControllerми будемо використовувати "Home" у json

  2. У додатку ми аналізуємо json, і я написав наведені нижче утилітні методи для динамічного отримання активності

Щоб отримати назву класу (тобто, якщо ми пройдемо додому, ми повернемося назад 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, мабуть, більшості розробників андроїдів, які шукають відповідь, потрібна версія kotlin, а не Java;)
Руслан Берозов

@RuslanBerozov Оператор позначив запитання як [java], тому я очікував би принаймні версії Java (додатковий Kotlin теж, звичайно).
LMD

@LMD вибачте, але op опублікував питання у 2012 році. Насправді важко уявити, що він тоді знав про Котліна. Справа в тому, що питання також позначено як [android], і сьогодні я бажаю версії Kotlin.
Руслан Берозов

-2

Можливо, це не найдоречніша відповідь на ваше запитання, але загалом погано жорстко кодувати літерали імен класів як рядки. Можливо, краще використовувати

Class<?> act = TestActivity.class;

синтаксис.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.