Obteniendo clase por su nombre

81

Si tengo una clase de actividad llamada TestActivity en mi aplicación, ¿hay alguna manera de obtener su clase por su nombre como en este ejemplo?

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

Respuestas:

158

use forName en su lugar ..

algo como esto..

 try {
    Class<?> act = Class.forName("com.bla.TestActivity");
 } catch (ClassNotFoundException e) {
        e.printStackTrace();
}
ngesh
fuente
30
También debe proporcionar el nombre completo del paquete. por ejemplo: com.bla.TestActivity como argumento para Class.forName
Richie
1
¿También puedes hacer algo para recibir Class<? extends SomeClass>?
Gobliins
@Gobliins No, el compilador no puede garantizar qué tipo de clase obtendrá, por lo que le da una Clase <?>. Si sabe qué tipo de clase va a recibir, tendrá que lanzarla (aún así, recibirá advertencias de lanzamiento sin marcar porque el yeso no es seguro).
Dylanthepiguy
@Gobliins Mira mi respuesta sobre cómo obtener una subclase de cierto tipo.
raphinesse
6

Puede usar Class::forNamepara obtener un objeto de clase de tipo desconocido. Si desea obtener una clase escrita, puede usarla Class::asSubclassen la clase devuelta por Class::forName:

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

Por supuesto, también tendrá que manejar un montón de tipos diferentes de excepciones. Como es habitual cuando se trata de reflexión.

raphinesse
fuente
6

El Class.forName parece tener excepciones. Esto es solo para ampliar lo anterior para abordar este problema.

try { t = Class.forName("com.package.classname"); } catch (Exception ignored){}
Patricio
fuente
La forma habitual en SO de responder así sería editar su respuesta. Aunque dado que las excepciones son abundantes en Java (y su código simplemente lo ignora), un comentario sería suficiente para abordarlo.
tsn
7
@crazyhatfish: parece que Patrick no ha tenido los privilegios de hacer nada útil excepto publicar su propia respuesta.
amess
3
@amess Vaya, tienes razón, olvido que los comentarios necesitan representante. Gracias por corregirme.
tsn
2

También tenía un requisito similar, tenía un json proveniente del backend que contiene la pantalla y el mapeo de actividades. Dado que el json es común para iOS / Android, no pudimos agregar términos como Activityen el json, así que esto es lo que hicimos

  1. En json para todos Activityo Viewcontrollers, use nombres simples, es decir, para HomeActivityy HomeViewControllerusaremos "Inicio" en el json

  2. En la aplicación, analizamos el json y he escrito los siguientes métodos de utilidad para obtener la actividad de forma dinámica

Para obtener el nombre de la clase (es decir, si pasamos a Inicio, volveremos com.package.HomeActivity)

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

Ahora para obtener la clase de la cadena

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

De esta manera puedo administrar fácilmente varias clases con el mismo método. Utilizo esto en una vista de reciclador donde cada una de mis células navega hacia una actividad diferente.

anoop4real
fuente
Tenga en cuenta que su respuesta está en Kotlin;) ¿Probablemente la modifique un poco para que sea Java?
LMD
@LMD probablemente la mayoría de los desarrolladores de Android que buscan una respuesta necesitan la versión kotlin, no java;)
Ruslan Berozov
@RuslanBerozov El operador ha etiquetado la pregunta como [java], por lo que esperaría al menos una versión de Java (Kotlin adicional también está bien, por supuesto).
LMD
@LMD lo siento, pero op publicó una pregunta en 2012. Es realmente difícil imaginar que él sabía sobre Kotlin en ese momento. El punto es que la pregunta también está marcada como [android], y hoy en día espero la versión de Kotlin preferiblemente.
Ruslan Berozov
-2

Puede que no sea la respuesta más relevante para su pregunta, pero generalmente es malo codificar los literales de nombres de clases como cadenas. Podría ser mejor usar

Class<?> act = TestActivity.class;

sintaxis.

Krivda
fuente