我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java怎么利用反射实现动态运行一行或多行代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java怎么利用反射实现动态运行一行或多行代码

这篇文章主要介绍“Java怎么利用反射实现动态运行一行或多行代码”,在日常操作中,相信很多人在Java怎么利用反射实现动态运行一行或多行代码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java怎么利用反射实现动态运行一行或多行代码”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Talk is cheap, show me the code!

先来看代码:

public class TestEval {public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {long start = System.currentTimeMillis();eval("int sum = 0; for (int i = 0; i < 1000; i++){sum += i;} System.out.println(sum);");long end = System.currentTimeMillis();System.out.println("运行耗时:"+(end-start)+"ms");}public static void eval(String code) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {//创建 eval.java 文件File file = new File("class="lazy" data-src/Eval.java");//创建缓冲输出流BufferedWriter buffer = new BufferedWriter(new FileWriter(file));//将 code 里面的内容写入 buffer 中buffer.write("public class Eval{\n"            //必须是 public class,否则无法访问。+ "public void test(){\n"+ code+"\n}"+"\n}");buffer.close();File parentFile = new File(file.getParent());//注意这里要补一个分隔符,不然会出错 File.pathSeparator//这可能是 class="lazy" data-src  和  class="lazy" data-src/ 表示意义的区别String parentPath = parentFile.getAbsolutePath()+File.separatorChar;//文件分隔符,只能在前面加,因为它是和平台有关的,//而这里我需要使用正斜杠,在windows平台下,默认是反斜杠parentPath = parentPath.replace('\\', '/');   //反斜杠要使用转义字符//Eval.class的位置,我的电脑上是 file:///F:/JavaProject/eval/class="lazy" data-src///注意最后面的文件分隔符//创建一个 URL 数组String url = "file:///"+parentPath;  System.out.println("测试使用,查看输出文件路径:"+url);//需要自己编译Java文件,产生 class 文件//下面这段代码用于编译文件,这是比较简单的了。//这个绝对路径是Java源文件的路径,使用javac编译获取 .class文件Process p = Runtime.getRuntime().exec("javac -encoding utf-8 "+file.getAbsolutePath()); InputStream compileError = p.getErrorStream();//下面javac 的编译信息,与在命令行中使用的输出结果一样,只是把错误信息放到了控制台进行输出,如果没有输出,代表编译成功。否则会有错误提示。byte[] b = new byte[1000];while (compileError.read(b) != -1) {System.out.println(new String(b));}        compileError.close();URL[] urls = {new URL(url)};//以默认的 ClassLoader 作为父 ClassLoader, 创建 URLClassLoaderURLClassLoader classLoader = new URLClassLoader(urls);Class<?> clazz = classLoader.loadClass("Eval");Object ob = clazz.newInstance();Method mtd = clazz.getMethod("test", new Class<?>[] {});  //使用 null 会有警告//执行方法!mtd.invoke(ob, new Object[] {});  //使用 null 会有警告classLoader.close();   //关闭 URLClassLoader 对象System.out.println("执行结束");}}

代码不多,但是用到了疯狂Java上的不少知识,比如使用 URLClassLoader 加载
字节码文件,因为一开始我是想使用 Class.forName(),但是发现总是提示找不到class文件,这似乎是 它的限制。然后我就想到了使用 URLClassLoader 这样加载的话,就不会有这个限制了。疯狂 Java 上面的例子是加载一个 jar 包,我这里就是加载一个单个 字节码文件(.class 文件)。

简要说明以下步骤:

首先将eval() 函数里面的 代码端,利用字符串拼接放入一个方法中,在放入一个类中:

       //创建 eval.java 文件File file = new File("class="lazy" data-src/Eval.java");//创建缓冲输出流BufferedWriter buffer = new BufferedWriter(new FileWriter(file));//将 code 里面的内容写入 buffer 中    buffer.write("public class Eval{\n"            //必须是 public class,否则无法访问。+ "public void test(){\n"+ code+"\n}"+"\n}");buffer.close();

然后利用Runtime.getRuntim.exec() 调用 javac 进行编译,因为源文件 是无法使用的,这是一种比较简单的编译文件的方式,我还见到了更为复杂的方式,但是限于水平,就采用了这种最简单的方式了。

获取字节码文件后,就要加载这个类了,但是使用 Class.forName() 这个方法,似乎不能加载任意类,必须是项目里面存在的类才行,这一点我还没明白,转念又想到了 ClassLoader 似乎可以解决这个问题,就是用了 URLClassLoader ,因为它可以从网络或者本地其他地方加载 字节码 文件,这一点非常方便。

加载字节码文件以后,就进入了反射的知识了。

//这里的url 是当前 字节码文件的路径,注意后面要带上文件分隔符 '/'URL[] urls = {new URL(url)};//以默认的 ClassLoader 作为父 ClassLoader, 创建 URLClassLoaderURLClassLoader classLoader = new URLClassLoader(urls);Class<?> clazz = classLoader.loadClass("Eval");Object ob = clazz.newInstance();Method mtd = clazz.getMethod("test", new Class<?>[] {});  //使用 null 会有警告//执行方法!mtd.invoke(ob, new Object[] {});  //使用 null 会有警告classLoader.close();   //关闭 URLClassLoader 对象

然后就可以运行了,但是不知到为什么,一开始运行特别慢,居然要 5000+ms,后来第二天中午我修改了以下以后,居然变快了。

下面是运行截图:

Java怎么利用反射实现动态运行一行或多行代码

Java怎么利用反射实现动态运行一行或多行代码

到此,关于“Java怎么利用反射实现动态运行一行或多行代码”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java怎么利用反射实现动态运行一行或多行代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java怎么利用反射实现动态运行一行或多行代码

这篇文章主要介绍“Java怎么利用反射实现动态运行一行或多行代码”,在日常操作中,相信很多人在Java怎么利用反射实现动态运行一行或多行代码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java怎么利用反射实
2023-07-05

关于Java利用反射实现动态运行一行或多行代码

这篇文章主要介绍了关于Java利用反射实现动态运行一行或多行代码,借鉴了别人的方法和书上的内容,最后将题目完成了,和大家一起分享以下解决方法,需要的朋友可以参考下
2023-05-14

golang运行时动态生成代码怎么实现

在Go语言中,可以使用`go/ast`和`go/printer`包来实现动态生成代码。首先,你需要使用`go/ast`包来创建一棵抽象语法树(AST),表示你要生成的代码。你可以使用`ast.NewIdent()`创建标识符,`ast.N
2023-10-26

Java怎么使用反射和动态代理实现一个View注解绑定库

本篇内容介绍了“Java怎么使用反射和动态代理实现一个View注解绑定库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用反射结合动态代理实
2023-06-30

java利用Future实现多线程执行与结果聚合的代码怎么写

java利用Future实现多线程执行与结果聚合的代码怎么写,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。场景网站智能问答场景,需要对多个分类查询,结果聚合展示由于每种分类
2023-06-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录