逍遥游

Java中利用scriptEngine执行代码语句

早在上学期的时候就知道了有这么一个可以执行代码的东西。当时Java的程序设计中有一道题就是让写一个计算机的界面和实现(主要是考GUI),记得当时是写了很繁琐(但是功能很少)的实现代码,基本就是计算“1+1”这种,不能有括号。有同学用了算法(名字忘了,是用来比较复杂的算式的,要用到逆波兰式)。

检查作业那天,因为结束的比较早,也没什么事,就留在机房听别人跟老师唠嗑。老师提到了计算器这件事,他说很多人偏离了题目的考察方向,其实计算结果这部分根本不需要我们自己去实现,有现成的函数,还提到了eval函数。我比较懒,再加上考试也不考,就没去深究,仅是记住有这么一个东西。前几天在做数据库(简直不能叫数据库)的时候,用处理SQL语句中where部分,要是自己处理那就太麻烦了,纠结了几天,突然想到了eval。

上网搜索一番,找到了示例代码,改改之后就移植到我的程序上了。

Eval函数是由scriptEngine类库提供,可以直接执行(脚本语言的)代码(不仅仅是计算算术表达式结果),这一特性在Java6 中加入。据我所研究,目前scriptEngine只能支持javascript语句,据说提供了一些接口,可以很容易的加入解析其他脚本语言的功能。(对牛人来说)

以下是测试通过的示例代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.util.*;
import java.util.logging.*;
import javax.script.*;
/**
*
* @author Newnius
*/
public class TestScriptEngine
{
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("js");
String query = "1==2 && 'asd'!='dsa'";//要执行的代码
long s = System.currentTimeMillis();
try {
String res = scriptEngine.eval(query) + "";
System.out.println("The result is: " + res);
} catch (ScriptException ex) {
Logger.getLogger(TestScriptEngine.class.getName()).log(Level.SEVERE, null, ex);
}
long e = System.currentTimeMillis();
System.out.println("Time costs: " + (e - s));
//test();
}
/**
* 获取scriptEngine的信息
*
*/
public static int test()
{
ScriptEngineManager manager = new ScriptEngineManager();
// 得到所有的脚本引擎工厂
List<ScriptEngineFactory> factories = (List<ScriptEngineFactory>)manager.getEngineFactories();
//遍历
for (ScriptEngineFactory factory : factories)
{
// 打印脚本信息
System.out.printf("Name: %s%n"
+ "Version: %s%n"
+ "Language name: %s%n"
+ "Language version: %s%n"
+ "Extensions: %s%n"
+ "Mime types: %s%n"
+ "Names: %s%n",
factory.getEngineName(),
factory.getEngineVersion(),
factory.getLanguageName(),
factory.getLanguageVersion(),
factory.getExtensions(),
factory.getMimeTypes(),
factory.getNames()
);
// 得到当前的脚本引擎
ScriptEngine engine = factory.getScriptEngine();
}
return 0;
}
}

结果:

1
2
The result is: false
Time costs: 16

注意,如果是需要进行大量的eval操作,先创建ScriptEngine,所有eval共用同一个对象,因为new的过程还是比较耗费时间的。

推荐一篇写的比较好的教程:java ScriptEngine 使用,本文也一定程度上借鉴了此文。

更精确的说明,参考Java官方文档:ScriptEngine (Java Platform SE 8 )


多说停止服务,disqus引导注册太过分,暂时不上评论系统了。有机会自己造轮子吧。邮箱:input@newnius.com