¿Hay alguna forma de instanciar una clase por nombre en Java?

102

Estaba mirando la pregunta: Crear una instancia de una clase a partir de su nombre de cadena, que describe cómo crear una instancia de una clase cuando tiene su nombre. ¿Hay alguna forma de hacerlo en Java? Tendré el nombre del paquete y el nombre de la clase y necesito poder crear un objeto con ese nombre en particular.

ict1991
fuente
Nos instanciar una clase y el resultado es un objeto (o: ejemplo ).
Andreas Dolk
1
La respuesta es sí, pero creo que debería preguntar si es una buena idea. Un gran poder (reflexión) conlleva una gran responsabilidad y solo debe usarlo si comprende y ha considerado las consecuencias.
c1moore

Respuestas:

238

Dos caminos:

Método 1: solo para clases que tienen un constructor sin argumentos

Si su clase tiene un constructor sin argumentos, puede obtener un Classobjeto usando Class.forName()y usar el newInstance()método para crear una instancia (aunque tenga en cuenta que este método a menudo se considera malvado porque puede anular las excepciones marcadas de Java).

Por ejemplo:

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

Método 2

Un enfoque alternativo más seguro que también funciona si la clase no tiene ningún constructor sin argumentos es consultar su objeto de clase para obtener su Constructorobjeto y llamar a un newInstance()método en este objeto:

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

Ambos métodos se conocen como reflexión . Por lo general, tendrá que detectar las diversas excepciones que pueden ocurrir, incluidas cosas como:

  • la JVM no puede encontrar o no puede cargar su clase
  • la clase que intentas crear una instancia no tiene el tipo correcto de constructores
  • el propio constructor lanzó una excepción
  • el constructor que intentas invocar no es público
  • Se ha instalado un administrador de seguridad que evita que se produzca la reflexión.
Simon Nickerson
fuente
hola, una vez que hayamos creado el objeto newInstance(), ¿podríamos devolverlo a nuestro propio objeto?
GMsoF
@Simon, ¿puedes dar más detalles / dar un consejo sobre el administrador de seguridad?
Ram
No entiendo esto. Quiero acceder a una clase en un archivo desconocido en algún otro directorio, solo tengo el nombre de la ruta / archivo como una cadena. Cadena "dir / unkonwn.java". Llamar a Class.forName ("dir / unknown") me da errores.
john ktejik
¿Cómo podemos lanzarnos instancea com.foo.MyClass? dado que com.foo.MyClass es solo una cadena
Sanket9394
14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
scibuff
fuente
15
Vale la pena mencionar que esto no funciona si la clase no tiene un constructor sin parámetros (y tiene otros constructores), o si el constructor sin parámetros es inaccesible.
Dawood ibn Kareem
3

use Class.forName ("Nombre de cadena de clase"). newInstance ();

Class.forName("A").newInstance();

Esto hará que la clase denominada A se inicialice.

Chandra Sekhar
fuente
No funciona para mí, incluso con el nombre del paquete antepuesto. :(
trusktr
3

Para que sea más fácil obtener el nombre completo de una clase para crear una instancia usando Class.forName(...), se podría usar el Class.getName()método. Algo como:

class ObjectMaker {
    // Constructor, fields, initialization, etc...
    public Object makeObject(Class<?> clazz) {
        Object o = null;

        try {
            o = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            // There may be other exceptions to throw here, 
            // but I'm writing this from memory.
            e.printStackTrace();
        }

        return o;
    }
}

Luego, puede convertir el objeto que obtiene a cualquier clase a la que pase makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);
Roberto
fuente
1
¿No puedes simplemente en clazz.newInstance()lugar del getNameentonces fromName?
user276648
1

Utilice la reflexión de Java

Crear nuevos objetos No hay equivalente a la invocación de métodos para constructores, porque invocar un constructor es equivalente a crear un nuevo objeto (para ser más precisos, crear un nuevo objeto implica tanto la asignación de memoria como la construcción del objeto). Entonces, el equivalente más cercano al ejemplo anterior es decir:

import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

que encuentra un constructor que maneja los tipos de parámetros especificados y lo invoca, para crear una nueva instancia del objeto. El valor de este enfoque es que es puramente dinámico, con búsqueda e invocación del constructor en tiempo de ejecución, en lugar de en tiempo de compilación.

kornero
fuente
0
String str = (String)Class.forName("java.lang.String").newInstance();
Chen Harel
fuente
0

Algo como esto debería funcionar...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();
Shashank Kadne
fuente
0

El uso newInstance()directo está en desuso a partir de Java 8. Debe usar Class.getDeclaredConstructor(...).newInstance(...)con las excepciones correspondientes.

Mel
fuente