Re: [javaSpain] Crear clase en tiempo de ejecución
yamsung lage <[email protected]> Tue, 11 Aug 2009 14:12:31 +0200
| Newsgroups | gmane.comp.java.javaspain |
|---|---|
| Message-ID | <[email protected]> |
Sebastian,
Muchas gracias esto es justamente lo que estoy preguntando y justo lo
que necesitaba "Carga dinámica de clases", el codigo esta estupendo y
me viene super bien.
Lo necesito así, porque las implementaciones de cierto comportamiento
tienen que ser ingresadas en "caliente".
He modificado para ponerlo un poco mas a mis necesidades. Lo
adjunto por si alguien lo necesitara alguna vez.
Ahora son tres clases: MakeTodayClass, ClaseACrear y MetodoClase.
-----------------------------
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
public class MakeTodayClass {
Date today = new Date();
ClaseACrear todayClass;
String todayMillis = Long.toString(today.getTime());
//String todayClass = "z_" + todayMillis;
String todaySource = todayClass + ".java";
public static void main(String args[]) {
MakeTodayClass mtc = new MakeTodayClass();
/* Clase a crear */
mtc.todayClass = new ClaseACrear();
mtc.todayClass.setNombrePaquete("sim.pelea.makeClass");
mtc.todayClass.setNombreClase("z_" + mtc.todayMillis);
mtc.todayClass.setNombreArchivo(mtc.todayClass.getNombreClase() + ".java");
// Crear metodo
MetodoClase metodo1 = new MetodoClase();
metodo1.setNombre("doit");
metodo1.setContenidoEjecutar(" System.out.println(\"" +
mtc.todayMillis + "\");");
MetodoClase metodo[] = new MetodoClase[1];
metodo[0] = metodo1;
mtc.todayClass.setMetodos(metodo);
mtc.createIt();
if (mtc.compileIt()) {
System.out.println("Running " + mtc.todayClass + ":\n\n");
mtc.runIt();
} else
System.out.println(mtc.todaySource + " is bad.");
}
public void createIt() {
try {
String nombre;
if (todayClass.nombrePaquete != null)
{
todayClass.nombreArchivoPackage =
todayClass.nombrePaquete.replace(".",
System.getProperty("file.separator"))+System.getProperty("file.separator")+todayClass.nombreArchivo;
nombre = todayClass.nombreArchivoPackage;
}
else
{
nombre = todayClass.nombreArchivo;
}
System.out.println(nombre+" - "+todayClass.nombrePaquete+" -
"+System.getProperty("file.separator"));
FileWriter aWriter = new FileWriter(nombre, true);
//Package
if (todayClass.nombrePaquete != null)
aWriter.write("package " + todayClass.nombrePaquete + ";\n\n");
//Import
if (todayClass.importClase != null)
for (int i = 0; i < todayClass.importClase.length; i++)
aWriter.write("import " + todayClass.importClase[i] + ";\n");
//Nombre clase
aWriter.write(todayClass.tipo+" class " + todayClass.nombreClase + "{\n");
//Metodos
if (todayClass.metodos != null)
for (int i = 0; i < todayClass.metodos.length; i++)
{
aWriter.write(" "+todayClass.metodos[i].tipo+"
"+todayClass.metodos[i].retorno+" "+todayClass.metodos[i].nombre+"()
{\n");
aWriter.write(todayClass.metodos[i].contenidoEjecutar);
aWriter.write("\n }\n");
}
//Final de clase
aWriter.write(" }\n");
aWriter.flush();
aWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
public boolean compileIt() {
String nombre;
if (todayClass.nombrePaquete != null)
{
nombre = todayClass.nombreArchivoPackage;
}else
{
nombre = todayClass.nombreArchivo;
}
String[] source = { new String(nombre) };
ByteArrayOutputStream baos = new ByteArrayOutputStream();
new sun.tools.javac.Main(baos, source[0]).compile(source);
// if using JDK >= 1.3 then use
// public static int com.sun.tools.javac.Main.compile(source);
return (baos.toString().indexOf("error") == -1);
}
@SuppressWarnings("unchecked")
public void runIt() {
String nombre;
if (todayClass.nombrePaquete != null)
{
nombre = todayClass.nombrePaquete+"."+todayClass.nombreClase;
}
else
{
nombre = todayClass.nombreClase;
}
try {
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(nombre);
Object iClass = thisClass.newInstance();
Method thisMethod =
thisClass.getDeclaredMethod(todayClass.metodos[0].nombre, params);
thisMethod.invoke(iClass, paramsObj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
--------------------------------------
public class ClaseACrear {
String nombrePaquete = null;
String importClase[];
String tipo = "public";
String nombreClase;
String nombreArchivo;
String nombreArchivoPackage;
MetodoClase metodos[];
public String getNombrePaquete() {
return nombrePaquete;
}
public void setNombrePaquete(String nombrePaquete) {
this.nombrePaquete = nombrePaquete;
}
public String[] getImportClase() {
return importClase;
}
public void setImportClase(String[] importClase) {
this.importClase = importClase;
}
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
public String getNombreClase() {
return nombreClase;
}
public void setNombreClase(String nombreClase) {
this.nombreClase = nombreClase;
}
public String getNombreArchivo() {
return nombreArchivo;
}
public void setNombreArchivo(String nombreArchivo) {
this.nombreArchivo = nombreArchivo;
}
public MetodoClase[] getMetodos() {
return metodos;
}
public void setMetodos(MetodoClase[] metodos) {
this.metodos = metodos;
}
}
------------------------------------
public class MetodoClase {
String tipo = "public";
String retorno = "void";
String nombre;
String contenidoEjecutar;
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
public String getRetorno() {
return retorno;
}
public void setRetorno(String retorno) {
this.retorno = retorno;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getContenidoEjecutar() {
return contenidoEjecutar;
}
public void setContenidoEjecutar(String contenidoEjecutar) {
this.contenidoEjecutar = contenidoEjecutar;
}
}
--------------------------------------
Un saludo,
2009/8/11 yamsung lage <[email protected]>:
> Sebastian,
>
> Muchas gracias esto es justamente lo que estoy preguntando y justo lo
> que necesitaba "Carga dinámica de clases", el codigo esta estupendo y
> me viene super bien.
>
> Lo necesito así, porque las implementaciones de cierto comportamiento
> tienen que ser ingresadas en "caliente".
>
> Hay alguna otra posibilidad de realizar la carga dinámica de clases ?
>
> Un saludo,
>
>
> 2009/8/10 Sebastian Gurin <sgurin-nLx/x0uvtyR/[email protected]>:
>> ojo con esto... No acabo de entender cuáles son tus requerimientos, pero si lo que quieres es persistir los objetos de tu applicación entonces no es por el lado de carga dinámica de clases que lo resuelves, sino por el lado de serialización de objetos java a xml. Son cosas distintas.
>>
>> Utiliza la carga dinámica de clases solo cuando ya no te quede otra... o sea, cuando el requerimiento sea que el usuario pueda insertar su propia implementación de cierto comportamiento en caliente (sin tener que detener la aplicación, agregar el código, compilar y reiniciar la aplicación).
>>
>> Si "las variantes" del comportamiento se conocen todas, en ese caso te conviene implementarlas a cada una de ellas en una clase java por separado, y utilizar el patrón de diseño Strategy para que el usuario pueda intercambiar de "variante" dinámicamente. Utiliza dynamic class loading solo cuando el requerimiento sea que las alternativas puedan ser definidas y "publicadas" dinámicamente.
>>
>> En el caso de que la carga dinámica de clases se alo que necesites, a continuación pego un código que hace los pasos 1, 2 y 3 que mencionas en otro mail. Suerte!
>>
>> import java.io.*;
>> import java.util.*;
>> import java.lang.reflect.*;
>>
>> public class MakeTodayClass {
>> Date today = new Date();
>> String todayMillis = Long.toString(today.getTime());
>> String todayClass = "z_" + todayMillis;
>> String todaySource = todayClass + ".java";
>>
>> public static void main (String args[]){
>> MakeTodayClass mtc = new MakeTodayClass();
>> mtc.createIt();
>> if (mtc.compileIt()) {
>> System.out.println("Running " + mtc.todayClass + ":\n\n");
>> mtc.runIt();
>> }
>> else
>> System.out.println(mtc.todaySource + " is bad.");
>> }
>>
>> public void createIt() {
>> try {
>> FileWriter aWriter = new FileWriter(todaySource, true);
>> aWriter.write("public class "+ todayClass + "{");
>> aWriter.write(" public void doit() {");
>> aWriter.write(" System.out.println(\""+todayMillis+"\");");
>> aWriter.write(" }}\n");
>> aWriter.flush();
>> aWriter.close();
>> }
>> catch(Exception e){
>> e.printStackTrace();
>> }
>> }
>>
>> public boolean compileIt() {
>> String [] source = { new String(todaySource)};
>> ByteArrayOutputStream baos= new ByteArrayOutputStream();
>>
>> new sun.tools.javac.Main(baos,source[0]).compile(source);
>> // if using JDK >= 1.3 then use
>> // public static int com.sun.tools.javac.Main.compile(source);
>> return (baos.toString().indexOf("error")==-1);
>> }
>>
>> public void runIt() {
>> try {
>> Class params[] = {};
>> Object paramsObj[] = {};
>> Class thisClass = Class.forName(todayClass);
>> Object iClass = thisClass.newInstance();
>> Method thisMethod = thisClass.getDeclaredMethod("doit", params);
>> thisMethod.invoke(iClass, paramsObj);
>> }
>> catch (Exception e) {
>> e.printStackTrace();
>> }
>> }
>> }
>>
>>
>>
>> On Sun, 9 Aug 2009 22:57:16 +0200
>> yamsung lage <[email protected]> wrote:
>>
>>> > Uhm... no veo por qué necesitarías esta clase. ¿Puedes poner un ejemplo?
>>>
>>> No entiendo lo que dices pero bueno trato de ponerte un ejemplo...
>>>
>>> Imaginate un programa en java que sea un simulador, entonces le debes
>>> pasar un archivo (Xml, o cualquiera). En este archivo se especifican
>>> unos objetos con sus datos miembros (ubicacion, color, etc) y sus
>>> funciones (cambiar de color, cambiar de posicion, girar, etc).
>>>
>>> Bueno la idea es que cuando el programa reciba el archivo, lo abra,
>>> identifique los objetos y los cree en tiempo de ejecución.
>>>
>>> Asi este archivo puede tener varios objetos, por ejemplo: Robot, caja,
>>> camion, etc. Y estos a su vez varias atributos con varios metodos.
>>>
>>> Sergio, espero haberme hecho explicar
>>>
>>>
>>> 2009/8/9 Sergio Arbeo <[email protected]>:
>>> >
>>> >
>>> > 2009/8/9 yamsung lage <[email protected]>:
>>> >
>>> >>
>>> >>
>>> >> Alguien tiene información de como crear una clase en tiempo de ejecucion
>>> >> ?.
>>> >>
>>> >> Por ejemplo, tengo un nombre Robot, entonces en tiempo de ejecucion
>>> >> quiero crear una clase de nombre Robot con varias funciones y
>>> >> atributos, y esta misma clase poder usarla en el momento.
>>> >
>>> >
>>> > Un saludo,
>>> >
>>> > Serabe
>>> >
>>> > --
>>> > http://sergio.arbeo.net
>>> > http://www.serabe.com
>>> >
>>>
>>
>>
>> --
>> Sebastian Gurin <sgurin-nLx/x0uvtyR/[email protected]>
>>
>