A partir del JDK1.1.x se incorporó a Java la posibilidad de introspectar clases. Esta característica fue fundamental para el posterior desarrollo de herramientas de desarrollo (valga la redundancia).
Basicamente, la idea es: Dado el nombre de una clase poder obtener una instancia invocando alguno de sus constructores. Luego, dado el nombre de un método, poderlo invocar, y así.
Obtener una Instancia dado el Nombre de la Clase
El caso más simple es invocar al constructor nulo (el que no recibe argumentos).
// defino el nombre de clase
String sClass = "java.awt.Frame";
// obtengo una instancia de Class para esa clase
Class clazz = Class.forName(sClass);
// obtengo la instancia a traves del ctor nulo
Object obj = clazz.newInstance();
Pero probablemente querramos instanciar la clase utilizando otro constructor, que reciba algún parámetro. Por ejemplo: el constructor que recibe un String.
Obtener un Método o un Constructor para luego invocarlo
Los métodos se identifican por su nombre y por un Class[] que indica el tipo y el orden de los argumentos que el método (o constructor) espera recibir.
Por ejemplo el método buscar(Connection con, int empno) se identifica así:
String nombre = "buscar";
Class[] args = {Connection.class, Integer.TYPE};
Notemos que el nómbre del método no es suficiente para identificarlo. Como el método puede estar sobrecargado necesitamos tambíen el Class[] para describir sus argumentos.
En el caso de los constructores no es necesario definir su nombre. Solo se necesita el Class[].
Luego, al momento de invocarlo necesitamos un Object[] con los valores de los parámetros que le vamos a pasar al método o constructor.
// obtengo una instancia de Class para esa clase
Class clazz = Class.forName(sClass);
// constructor que vamos a utilizar
Class cArgs[] = { String.class };
Object oParams[] = { new String("Demo Reflection") };
// obtengo el constructor que recibe (en este caso) un String
Constructor ctor = clazz.getConstructor(cArgs);
// invoco el constructor pasandole los argumentos que espera
Object obj = ctor.newInstance(oParams);
Invocar un Método sobre un Objeto
Ahora vamos a invocarle un método al objeto obj. El método setSize(int,int). Definimos el Class[] y el Object[] con los valores de los argumentos.
Recordemos que ya tenemos los objetos clazz (Class apuntando a java.awt.Frame) y obj (la instancia que obtuvimos luego de invocar al constructor que recibe un String).
// defino el nombre del metodo
String sMetodo1 = "setSize";
// defino el Class[] con el que voy a indicar que el metodo que espero
// obtener recibe dos parametros de tipo int
Class cArgs1[] = { Integer.TYPE,Integer.TYPE };
// defino un array de argumentos. Al metodo le voy a pasar
// los argumentos: 300,300
Object oParams1[] = { new Integer(300), new Integer(300) };
// obtengo el metodo identificado por su nombre y un Class[]
Method mtd1 = clazz.getMethod(sMetodo1,cArgs1);
// lo invoco sobre el objeto obj
mtd1.invoke(obj,oParams1);
El ejemplo que veremos a continuación, que es equivalente a este segmento de código:
Frame f=new Frame("Demo Reflection");
f.setSize(300,300);
f.setVisible(true);
TestReflection.java
El resultado es: