Klasse beim Namen bekommen

81

Wenn ich in meiner Anwendung eine Aktivitätsklasse namens TestActivity habe, gibt es eine Möglichkeit, die Klasse anhand ihres Namens wie in diesem Beispiel zu ermitteln:

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

Antworten:

158

Verwenden Sie stattdessen forName .

etwas wie das..

 try {
    Class<?> act = Class.forName("com.bla.TestActivity");
 } catch (ClassNotFoundException e) {
        e.printStackTrace();
}
ngesh
quelle
30
Sie müssen auch den vollständigen Paketnamen angeben. Beispiel: com.bla.TestActivity als Argument für Class.forName
Richie
1
Können Sie auch etwas tun, um zu erhalten Class<? extends SomeClass>?
Gobliins
@Gobliins Nein - der Compiler kann nicht garantieren, welche Art von Klasse Sie erhalten werden, daher gibt er Ihnen eine Klasse <?>. Wenn Sie wissen, welche Art von Klasse Sie erhalten werden, müssen Sie sie wirken (trotzdem erhalten Sie ungeprüfte Warnungen, weil die Besetzung nicht sicher ist).
Dylanthepiguy
@Gobliins Schauen Sie sich meine Antwort an, wie Sie eine Unterklasse eines bestimmten Typs erhalten.
Raphinesse
6

Sie können verwenden Class::forName, um ein Klassenobjekt unbekannten Typs abzurufen. Wenn Sie eine typisierte Klasse erhalten möchten, können Sie diese Class::asSubclassfür folgende Klasse verwenden Class::forName:

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

Natürlich müssen Sie auch eine Reihe verschiedener Arten von Ausnahmen behandeln. Wie beim Umgang mit Reflexion üblich.

raphinesse
quelle
6

Die Class.forName scheint Ausnahmen zu haben. Dies dient nur dazu, das oben Gesagte zu erweitern, um dieses Problem zu beheben.

try { t = Class.forName("com.package.classname"); } catch (Exception ignored){}
Patrick
quelle
Die übliche Methode für SO, so zu antworten, besteht darin , ihre Antwort zu bearbeiten . Obwohl es in Java zahlreiche Ausnahmen gibt (und Ihr Code dies einfach ignoriert), würde ein Kommentar ausreichen, um dies zu beheben.
crazyhatfish
7
@crazyhatfish - Es scheint, als hätte Patrick möglicherweise nicht die Privilegien gehabt, etwas Hilfreiches zu tun, außer seine eigene Antwort zu posten.
Amess
3
@amess Whoops, dein Recht, ich vergesse Kommentare brauchen rep. Danke, dass du mich verbessert hast.
crazyhatfish
2

Ich hatte auch eine ähnliche Anforderung, ich hatte einen JSON aus dem Backend, der den Bildschirm und die Aktivitätszuordnung enthält. Da der JSON für iOS / Android gemeinsam ist, konnten wir dem JSON keine Begriffe wie hinzufügen Activity, also haben wir dies getan

  1. Verwenden Sie in json für alle Activityoder Viewcontrollerseinfache Namen, dh für HomeActivityund HomeViewControllerwir verwenden "Home" im json

  2. In der App analysieren wir den JSON und ich habe die folgenden Dienstprogrammmethoden geschrieben, um die Aktivität dynamisch abzurufen

Um den Namen der Klasse zu erhalten (dh wenn wir nach Hause kommen, werden wir zurückkommen com.package.HomeActivity)

    fun getClassInfoFor(name: String, context: Context):String{
        var str = "${context.getPackageName()}.${name}Activity"
        return str
    }

Nun, um Klasse aus String zu bekommen

        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()
        }

Auf diese Weise kann ich problemlos mehrere Klassen mit derselben Methode verwalten. Ich verwende dies in einer Recycler-Ansicht, in der jede Zelle zu einer anderen Aktivität navigiert.

anoop4real
quelle
Bitte beachte, dass deine Antwort in Kotlin ist;) Ändere sie wahrscheinlich ein wenig, um sie zu Java zu machen?
LMD
@LMD wahrscheinlich brauchen die meisten Android-Entwickler, die nach einer Antwort suchen, die Kotlin-Version, nicht Java;)
Ruslan Berozov
@ RuslanBerozov Die Operation hat die Frage als [Java] markiert, daher würde ich mindestens eine Java-Version erwarten (zusätzliches Kotlin ist natürlich auch in Ordnung).
LMD
@LMD sorry, aber op hat 2012 eine Frage gestellt. Es ist wirklich schwer vorstellbar, dass er zu dieser Zeit von Kotlin wusste. Der Punkt ist, dass die Frage auch als [android] markiert ist, und heutzutage erwarte ich vorzugsweise die Kotlin-Version.
Ruslan Berozov
-2

Es ist möglicherweise nicht die relevanteste Antwort auf Ihre Frage, aber es ist im Allgemeinen schlecht, Klassennamenliterale als Zeichenfolgen fest zu codieren. Es könnte besser sein, zu verwenden

Class<?> act = TestActivity.class;

Syntax.

Krivda
quelle