如题:
要实现的要求是:
在运行期定义一个类的名字、属性、方法,并用反射的方式实例化这个类
请注意要求是运行期、定义
哪位大哥能给我一个思想,最好有核心代码,这100分是给大家散的,对我启发特别大的朋友另赠500分
谢谢大家
25 个解决方案
很简单啊
Class c=Class.forName(className);
c.getConstructor...
c.getDeclaredMethod...
最基本的反射。。
简单
俺有写有一个程序:http://community.csdn.net/Expert/TopicView.asp?id=3818601
java.lang.Class and java.lang.Reflect
自己看吧。
运行期定义应该不行的吧。
除非你自己用runtime.exec javac 来编译在用classloader加载
在运行期构建某个已有的class的话就也没有什么难度了吧。
但是我看的不太明白你的意思,你说在运行期间定义,是不是运行期间更改类的结构,这样的话,估计不行。
据我所知apache jakarta 的 BCEL 就是来做这个事情的,你可以参考一下,我没有用过
我好像贴过一个学习cglib的例子,不过找不到了 :(
以前我们在讨论classloader和资源回收的时候好像涉及到过这样的问题。呵呵。
import java.net.*;
import java.io.*;
import java.lang.reflect.*;
/**
* class to test class reloading
*/
public class CLTest{
public static void main(String[] args) {
String cs = "public class Foo { public static int getNum(){ int tmp = 666;System.out.println(\"value is \"+tmp);return tmp;}}";
int i = 100;
Runtime r = Runtime.getRuntime();
try {
// loop until we press enter
while (System.in.available() == 0) {
modifyClass(cs,i);
int ires = execClass();
System.out.println("ires="+ires);
i+=100;
r.gc();
System.out.println(" free mem: "+ r.freeMemory() + " of " + r.totalMemory());
}
} catch (Exception e){
System.out.println(e);
System.exit(0);
}
}
// replace the 666 in the code argument with the number i
// write it as file Foo.Java and compile it
public static void modifyClass(String code, int i) {
Runtime r = Runtime.getRuntime();
BufferedWriter writer;
File foo=new File("E:\\tmp\\Foo.java");
foo.delete();
String newcode = code.replaceFirst("666",""+i);
try {
writer = new BufferedWriter(new FileWriter(foo,false));
writer.write(newcode,0,newcode.length());
writer.close();
//System.out.println("Written ..."+newcode);
Process p =r.exec("javac E:\\tmp\\Foo.java");
p.waitFor();
System.out.println("compile complete");
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}
}
// get a new class loader, load the class and run the getNum method
public static int execClass() {
Object res=null;
try {
URLClassLoader cl;
URL[] urls = {new File("E:\\tmp/").toURL()};
cl = new URLClassLoader(urls);
Class c = cl.loadClass("Foo");
Method m = c.getMethod("getNum",null);
res = m.invoke (null,null);c=null;
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}
return ((Integer)res).intValue();
}
}
“在运行期定义”似乎不是一个很好的主意,其涉及到要在运行期间编译一个新的类。
楼主的问题不能用其它的方法解决??
在系统启动时,各个控制类需要创建,各线程、各模块需要初始化。在系统关闭时,尚在处理的任务必须存储,各模块占用的线程将先后释放。我们设计由一个主控类开控制系统的启动和关闭。
使用的是这种技术
我现在搞的项目是这个:把源代码给老兄看看,还没有完工
public class SubSystemController
extends java.lang.Thread {
/**
* SubSystemController:初始化内部的句柄注册集合
*/
private SubSystemController() {
}
/**
* 实例化本类的一个对象
*/
static SubSystemController sub = new SubSystemController();
/**
* 用于存储各个模块实例的模板
*/
public static java.util.HashMap moduleLib = new java.util.HashMap();
/**
* 是否在运行
*/
public static boolean isRun;
/**
* 是否停止
*/
public static boolean stop = false;
public static SubSystemController getInstance() {
return sub;
}
/**
* startSS 启动系统
* <p>Process:启动子系统,创建各个控制类,初始化各线程、各模块
* <br>并注册它们的句柄</p>
*/
public void startSS() {
this.isRun = true;
System.out.println("System start!");
/**
* 初始化各个模块
*/
ConfigManager configManager = new ConfigManager();
ObjectGettingManager objectGettingManager = new
ObjectGettingManager();
AlarmStatusManager alarmStatusManager = new AlarmStatusManager();
AlarmAnalyser alarmAnalyser = new AlarmAnalyser();
TicketCreator ticketCreator = new TicketCreator();
AnounceContentGenerator anounceContentGenerator = new
AnounceContentGenerator();
/**
* 注册各个模块的句柄
*/
moduleLib.put("configManager", configManager);
moduleLib.put("objectGettingManager", objectGettingManager);
moduleLib.put("alarmStatusManager", alarmStatusManager);
moduleLib.put("ticketCreator", ticketCreator);
moduleLib.put("alarmAnalyser", alarmAnalyser);
moduleLib.put("anounceContentGenerator", anounceContentGenerator);
try {
/**
* AlarmAnalyser开始轮询
*/
}
catch (Exception e) {
/**
* Error Handling
*/
}
}
/**
* shutoffSS 关闭子系统
* <p>Process:在系统关闭时,各模块占用的线程将先后释放,尚在处理的任务必须存储;
*/
public void shutoffSS() {
moduleLib.remove("configManager");
moduleLib.remove("objectGettingManager");
moduleLib.remove("alarmStatusManager");
moduleLib.remove("ticketCreator");
moduleLib.remove("alarmAnalyser");
moduleLib.remove("anounceContentGenerator");
stop = true;
try {
//Thread.yield();
}
catch (Exception ex) {
}
}
/**
* run:运行期方法,保持单独的线程,定时打印时间。
*/
public void run() {
this.isRun = true;
// while (stop == false) {
// try {
// Thread.sleep(2000) ;
// System.out.println(new java.util.Date()) ;
// }
// catch (Exception e) {
// e.printStackTrace() ;
// }
// }
System.out.println("System shut off!");
}
}
谢谢各位,大家贴的代码我会好好看一下的,
有的朋友还没有了解我的意思,其实很简单
就是说一个类本来是不存在的,只是我需要的时候才定义他.
我认为反射机制是可以解决这个问题的,当然还需要classloader的配合,有没有兄弟又跟好的建议??
最顶楼的几个兄弟是没有理解我的意思的,最简单的反射我当然理解,要是真的有这么简单,我也不会拿500分出来了
一种笨的方法是用字符串生成对象,然后调用当地javac编译器动态编译,然后用Reflection调用。。。
另一种方法是采用类似Dynamic Proxy那样的东西,实现InvocationHandler
也参考
Janino
http://www.janino.net/
to: taglib(温习中)
你是说的代理模式吧,我也想过这种方式,但好像不行,能不能在说得具体点??
to : jiangxuhong217(红红)
说实话,我没有找到你是在源程序中的哪里定义的一个类,能否指明?
楼主去看看javassist,里面就有一个动态生成class的例子
参考BeanShell的做法
http://www.beanshell.org
或ASM
http://asm.objectweb.org