Java 动态执行java代码_java-java动态性之反射,动态编译,动态执行js及动态字节码操作...

1 packagecom.reflection;2

3 importjava.lang.reflect.Constructor;4 importjava.lang.reflect.Field;5 importjava.lang.reflect.InvocationTargetException;6 importjava.lang.reflect.Method;7 importjava.lang.reflect.ParameterizedType;8 importjava.lang.reflect.Type;9 importjava.util.ArrayList;10 importjava.util.List;11

12 importjavax.script.ScriptEngine;13 importjavax.script.ScriptEngineManager;14 importjavax.script.ScriptException;15 importjavax.tools.JavaCompiler;16 importjavax.tools.ToolProvider;17

18 importcom.sun.javafx.collections.MappingChange.Map;19

20 /*

21 * Java动态性:22 * 动态语言:23 * 程序运行时,可以改变程序结构或变量类型,Java并非动态语言,但其拥有动态性,利用反射机制以及字节码操作获得类似动态语言的特性.24 * 一.反射机制:可以于运行时加载,探知,使用编译期间完全未知的类。25 * (1)PS:程序在运行状态中,可以动态的加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性26 * (2)操作方式:Class c=Class.forName("com.reflection.Reflect");27 * (3)反射:加载完类之后,在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象),该对象包含了完整的类的结构信息,通过这个对象可以看到类的结构,这便是反射。28 * (4)Class类是Reflection的根源:针对任何想要动态加载,运行的类,唯有先获得相应的Class对象。29 * (5)获取Class对象的三种方式: getClass(),Class.forName(),.class语法30 * (6)反射机制的常见作用:31 * 动态加载类,动态获取类的信息(属性,方法,构造器)/动态构造对象/动态调用类和对象的任意方法及构造器/32 * 动态调用和处理属性/获取泛型信息/处理注解33 * (7)反射机制的性能问题:34 * 利用反射执行类方法执行速度大概为类普通方法执行速度的1/30,也就是很慢,效率低,加上setAccessible()后可提高效率35 * setAccessible():启用和禁用访问安全检查的开关,值为true,则表示取消访问安全检查,反之36 *37 * 二.动态编译:38 * 动态编译的两种做法:39 * (1)通过Runtime调用javac,启动新的进程去操作40 * ->Runtime run=Runtime.getRuntime();41 * Process process=run.exec("java -cp +类文件绝对路径");42 * (2)通过JavaCompiler动态编译43 * ->JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();44 * int result=compiler.run(null,null,null,sourceFile);45 * 第一个参数:为java编译器提供参数 InputStream46 * 第二个参数:得到java编译器的输出信息 OutputStream47 * 第三个参数:接收编译器的错误信息48 * 第四个参数:可变参数(为String数组)能传入一个或多个java源文件49 * 返回值:1表示编译成功,0表示编译失败50 *51 * 三.动态执行JavaScript代码:52 * Java脚本引擎:53 * 使得java的应用程序可以通过一套固定的接口与各种脚本引擎交互,从而达到在Java平台上调用各种脚本语言的目的。54 * 可以把一些复杂异变的业务逻辑交给脚本语言处理,大大提高开发效率55 * (1)获得脚本引擎对象:56 * ScriptEngineManager sem=new ScriptEngineManager();57 * ScriptEngine engine=sem.getEngineByName("javascript");58 * 功能:59 * (1)获取脚本程序输入,通过脚本引擎运行脚本并返回运行结果,这是最核心的接口。 JS使用了Rhino60 * (2)通过脚本引擎的运行上下文在脚本和Java平台间交换数据。61 * (3)通过Java应用程序调用脚本函数。62 *63 * 四.动态字节码操作:64 * 功能:动态生成新的类,动态改变某个类的结构(增加,删除,修改 新的属性/方法 )65 * 优势:比反射的开销小,性能高,Javassist性能高于反射,低于ASM66 * 常见的字节码操作类库:67 * BCEL:在实际的JVM指令层次上进行操作,拥有丰富的JVM指令级支持68 * ASM:是一个轻量级java字节码操作框架,直接涉及到JVM底层的操作和指令69 * CGLIB:是一个强大的,高性能,高质量的code生成类库,基于ASM实现70 * Javassist:是一个开源的分析,编辑和创建字节码的类库,性能较ASM差,较cglib差不多,使用简单71 * ->最外层的API和JAVA反射包中的API颇为相似:72 * 主要由CtClass,CtMethod以及CtField几个类组成,73 * 用以执行和JDK反射API中java.lang.Class,java.lang.reflect.Method74 * 以及java.lang.reflect.Method.Field相同的操作75 *76 * 局限性:77 * 不支持泛型,枚举,不支持注释修改,但可以通过底层的javassist类解决78 * 不支持数组的初始化,内部类和匿名类,不支持continue,break语句还有部分继承关系79 *80 */

81

82 @SuppressWarnings("all")83 public classReflect {84

85 public static void main(String[] args) throwsInstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ScriptException {86

87 try{88 getInfoByReflect();89 useConstructorByReflect();90 useReflectMethod();91 getTypeAll();92 /*testComplier();*/

93 scriptEngine();94 } catch(ClassNotFoundException e) {95 e.printStackTrace();96 }97

98 }99

100 //通过反射获取Class对象里面对应类的属性

101 public static void getInfoByReflect() throwsClassNotFoundException {102 //获取Student类的Class对象

103 Class c=Class.forName("com.reflection.Student");104 //通过该Class对象获取该类的具体名字(包含包名)及类名

105 String realName=c.getName();106 String name=c.getSimpleName();107 System.out.println("具体名字:"+realName+" 类名:"+name);108

109 //获取类的属性110 //Field[] field=c.getFields();//只能获取public的属性

111 Field[] fields=c.getDeclaredFields();112 //获取所有属性

113 for(Field f:fields) {114 System.out.println("属性:"+f);115 }116 /*获取类所有的方法117 PS:如果方法有参,则必须参数类型对应的Class对象118 Method m1=c.getDeclaredMethod("getName", null);119 Method m2=c.getDeclaredMethod("setName", String.class);*/

120 Method[] methods=c.getMethods();121 for(Method m:methods) {122 System.out.println("方法:"+m);123 }124 //获取类所有的构造器

125 Constructor[] constructors=c.getConstructors();126 for(Constructor con:constructors) {127 System.out.println("构造器:"+con);128 }129 }130

131 //通过反射调用构造方法,构造对象,创建记录并将其放入集合中,然后打印出来

132 public static void useConstructorByReflect() throwsClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {133 Class c=Class.forName("com.reflection.Student");134 Constructor cr=c.getConstructor(int.class,String.class,String.class);135 Student s1=cr.newInstance(123,"张三","软件一班");136 Student s2=cr.newInstance(456,"李四","软件二班");137 List list=new ArrayList();138 list.add(s1);139 list.add(s2);140 System.out.println("编号:"+list.get(0).getId()+" 姓名:"+list.get(0).getName()+" 班级:"+list.get(0).getCname());141 System.out.println("编号:"+list.get(1).getId()+" 姓名:"+list.get(1).getName()+" 班级:"+list.get(1).getCname());142 }143

144 //利用对象里面的方法来对 Student实体类进行初始化数据操作

145 public static void useReflectMethod() throwsClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {146 Class c2=Class.forName("com.reflection.Student");147 Student s3=(Student)c2.newInstance();148 //先获取Class对象里面的方法

149 Method m2=c2.getDeclaredMethod("setName", String.class);150 //使用该方法

151 m2.invoke(s3, "王五");152 System.out.println("方法实现后获取值为:"+s3.getName());153 }154

155 //对包含泛型的方法进行处理

156 public static void getTypeAll() throwsNoSuchMethodException, SecurityException {157 //获取指定方法泛型参数信息

158 Method m3=Reflect.class.getMethod("test01",Map.class,List.class);159 Type[] types=m3.getGenericParameterTypes();160 for(Type t:types) {161 System.out.println("#"+t);162 if (t instanceofParameterizedType) {163 Type[] generalType=((ParameterizedType) t).getActualTypeArguments();164 for(Type gtype:generalType) {165 System.out.println("泛型类型为:"+gtype);166 }167 }168 }169 //获取指定方法泛型返回值信息

170 Method m4=Reflect.class.getMethod("test02", null);171 Type returnType=m4.getGenericReturnType();172 if(returnType instanceofParameterizedType) {173 Type[] generalType=((ParameterizedType) returnType).getActualTypeArguments();174 for(Type gtype:generalType) {175 System.out.println("返回值泛型类型为:"+gtype);176 }177 }178 }179

180 //动态编译方法实现

181 public static voidtestComplier() {182 JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();183 int result=compiler.run(null,null,null,"");184 System.out.println(result==0?"编译成功":"编译失败");185 }186

187 //构造一个带泛型参数的方法

188 public void test01(Map map,Liststu){189 System.out.println("测试");190 }191 //构造一个带泛型返回值的方法

192 public Maptest02(){193 return null;194 }195

196 //脚本引擎简单使用

197 public static void scriptEngine() throwsScriptException {198 //获取脚本引擎对象

199 ScriptEngineManager sem=newScriptEngineManager();200 ScriptEngine engine=sem.getEngineByName("javascript");201 //定义变量存储到脚本引擎的上下文中

202 engine.put("msg", "我很喜欢敲代码!");203 System.out.println("获取到的信息为:"+engine.get("msg"));204

205 String str="var user= {name:'张三',age:18};";206 str +="print('用户名:'+user.name);";207 //执行脚本

208 engine.eval(str);209 //利用脚本引擎执行javascript的函数

210 String st="function time() { var a=10,b=a*10;print('最终结果为:'+b);}; time();";211 engine.eval(st);212 }213 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值