表达式引擎aviator
2016-03-02 20:28
357 查看
Aviator是一个轻量级、高性能的Java表达式执行引擎, 本文内容主要来自于官方文档
简介
包依赖
使用手册
执行表达式
使用变量
exec 方法
调用函数
自定义函数
编译表达式
访问数组和集合
三元操作符
正则表达式匹配
变量的语法糖
nil 对象
日期比较
大数计算和精度
字面量表示
运算
类型转换和提升
decimal 的计算精度
强大的 seq 库
两种运行模式
调试信息
语法手册
数据类型
操作符
算术运算符
逻辑运算符
关系运算符
位运算符
匹配运算符
三元运算符
内置函数
相关链接
Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢?
Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上依赖包也才450K,不算依赖包的话只有 70K; 当然, Aviator的语法是受限的, 它不是一门完整的语言, 而只是语言的一小部分集合。
其次, Aviator的实现思路与其他轻量级的求值器很不相同, 其他求值器一般都是通过解释的方式运行, 而Aviator则是直接将表达式编译成Java 字节码, 交给JVM去执行。简单来说, Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎 之间。
Aviator支持大部分运算操作符, 包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(
并且支持操作符的优先级和括号强制优先级, 具体请看后面的操作符列表, 支持自定义函数.
Aviator依赖了
使用Aviator可以添加下面的maven依赖:
Aviator的使用都是集中通过
最简单的例子, 执行一个计算
细心的朋友肯定注意到结果是
任何整数都将转换成
包括用户传入的变量数值。这个例子的打印结果将是正确答案
想让Aviator对你
很简单, 传入你的名字, 让Aviator负责字符串的相加:
上面的例子演示了怎么向表达式传入变量值, 表达式中的
默认为
将
上面例子中的
可以参与正则匹配, 可以与任何对象相加, 任何对象与
Aviator 2.2 开始新增加一个
可以更方便地传入变量并执行, 而不需要构造
只要在
不需要构建
Aviator 支持函数调用, 函数调用的风格类似 lua, 下面的例子获取字符串的长度:
再用
通过
然后通过函数
函数可以嵌套调用。
Aviator 的内置函数列表请看后面。
Aviator 除了内置的函数之外,还允许用户自定义函数,只要实现
并注册到
通常来说你并不需要实现所有的方法, 只要根据你的方法的参 数个数, 继承
可以看一个例子,我们实现一个
注册函数通过
移除可以通过
上面提到的例子都是直接执行表达式, 事实上 Aviator 背后都帮你做了编译并执行的工作。 你可以自己先编译表达式, 返回一个编译的结果, 然后传入不同的
提高性能, 这是更推荐的使用方式:
通过
当要执行表达式的时候传入
表达式中使用了括号来强制优先级, 这个例子还使用了
比较运算符
也可以用于
甚至是任何用户传入的两个都实现了
编译后的结果你可以自己缓存, 也可以交给 Aviator 帮你缓存,
如果你决定缓存编译结果, 可以通过:
将
那么下次编译同一个表达式的时候将直接返回上一次编译的结果。
使缓存失效通过:
方法。
可以通过中括号去访问数组和
可以通过
一个例子:
Aviator 不提供
但是提供了三元操作符
java 没有什么不同:
Aviator 的三元表达式对于两个分支的结果类型并不要求一致,可以是任何类型,这一点与 java 不同。
Aviator 支持类 Ruby 和 Perl 风格的表达式匹配运算,通过
如下面这个例子匹配 email 并提取用户名返回:
型, 因此可以用于三元表达式判断,匹配成功的时候返回
1,也就是用户名,否则返回
Aviator 在表达式级别支持正则表达式,通过
达式可以用于匹配(作为
Aviator 会自动将匹配成功的分组放入
Aviator 的正则表达式规则跟 Java 完全一样,因为内部其实就是使用
Aviator 有个方便用户使用变量的语法糖, 当你要访问变量
那么你可以通过
推广开来也就是说 Aviator 可以将变量声明为嵌套访问的形式。
并且是
java 中的
java 中
Aviator 规定,任何对象都比
java 一样显示为
Aviator 并不支持日期类型,如果要比较日期,你需要将日期写字符串的形式,并且要求是形如 “yyyy-MM-dd HH:mm:ss:SS”的字符串,否则都将报错。 字符串跟
也就是说
从 2.3.0 版本开始,aviator 开始支持大数字计算和特定精度的计算, 本质上就是支持
这两种类型在 aviator 中简称 为
类似
Java 语言里是没办法编译通过 的, 因为它超过了
只能用
aviator 通过包装,可 以直接支持这种大整数的计算,例如:
结果为类型
以大写字母
都是
超过
以大写字母
如
都是
用户也可以通过变量传入这两种类型来参与计算。
aviator重载了基本算术操作符来支持这两种新类型:
当
Java 的
默认 Aviator 的计算精度为
通过:
即可设置,更多关于
javadoc 文档。
aviator 拥有强大的操作集合和数组的
aviator 中, 数组以及
例如,假设我有个
我们可以:
求长度:
求和:
过滤:
过滤出
判断元素在不在集合里:
排序:
遍历整个集合:
默认
你可以修改为编译速度优先,这样不会做编译优化:
从 2.1.1.版本开始,Aviator允许设置输出每个表达式生成的字节码,只要设置
方便用户做跟踪和调试。默认是输出到标准输出,你可以改变输出指向:
下面是 Aviator 详细的语法规则定义。
任何以大写字母
任何以大写字母
其他的任何整数都将被转换为
其他任何浮点数都将被转换为
超过
其中
2.3.0 版本开始引入的。数字还支持十六进制(以
以及科学计数法,如
java 的
以
实现为
变量类型: 与 Java 的变量命名规则相同,变量的值由用户传入
java 中的
也可以参与
规定任何类型都大于
用户传入的变量值如果为
Aviator 支持常见的算术运算符,包括
Aviator 规定,任何类型与
Avaitor 的支持的逻辑运算符包括,一元否定运算符
Aviator 支持的关系运算符包括
关系运算符可以作用于
不同类型除了
Aviator 支持所有的 Java 位运算符,包括
匹配运算符
匹配成功后,
Aviator 没有提供
而
Aviator 表达式,并且不要求
GitHub上的资料
简介
包依赖
使用手册
执行表达式
使用变量
exec 方法
调用函数
自定义函数
编译表达式
访问数组和集合
三元操作符
正则表达式匹配
变量的语法糖
nil 对象
日期比较
大数计算和精度
字面量表示
运算
类型转换和提升
decimal 的计算精度
强大的 seq 库
两种运行模式
调试信息
语法手册
数据类型
操作符
算术运算符
逻辑运算符
关系运算符
位运算符
匹配运算符
三元运算符
内置函数
相关链接
简介
Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢?Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上依赖包也才450K,不算依赖包的话只有 70K; 当然, Aviator的语法是受限的, 它不是一门完整的语言, 而只是语言的一小部分集合。
其次, Aviator的实现思路与其他轻量级的求值器很不相同, 其他求值器一般都是通过解释的方式运行, 而Aviator则是直接将表达式编译成Java 字节码, 交给JVM去执行。简单来说, Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎 之间。
Aviator支持大部分运算操作符, 包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(
=~)、三元表达式(
?:),
并且支持操作符的优先级和括号强制优先级, 具体请看后面的操作符列表, 支持自定义函数.
包依赖
Aviator依赖了commons-beanutils,
使用Aviator可以添加下面的maven依赖:
<dependency> <groupId>com.googlecode.aviator</groupId> <artifactId>aviator</artifactId> <version>2.3.3</version> </dependency>
使用手册
执行表达式
Aviator的使用都是集中通过com.googlecode.aviator.AviatorEvaluator这个入口类来处理,
最简单的例子, 执行一个计算
1+2+3的表达式:
import com.googlecode.aviator.AviatorEvaluator; public class TestAviator { public static void main(String[] args) { Long result = (Long) AviatorEvaluator.execute("1+2+3"); System.out.println(result); } }
细心的朋友肯定注意到结果是
Long,而不是
Integer。这是因为
Aviator的数值类型仅支持
Long和
Double,
任何整数都将转换成
Long, 任何浮点数都将转换为
Double,
包括用户传入的变量数值。这个例子的打印结果将是正确答案
6。
使用变量
想让Aviator对你say hello吗?
很简单, 传入你的名字, 让Aviator负责字符串的相加:
public class TestAviator { public static void main(String[] args) { String yourName = "Michael"; Map<String, Object> env = new HashMap<String, Object>(); env.put("yourName", yourName); String result = (String) AviatorEvaluator.execute(" 'hello ' + yourName ", env); System.out.println(result); // hello Michael } }
上面的例子演示了怎么向表达式传入变量值, 表达式中的
yourName是一个变量,
默认为
null, 通过传入
Map<String,Object>的变量绑定环境,
将
yourName设置为你输入的名称。
env的
key是变量名,
value是变量的值。
上面例子中的
'hello '是一个
Aviator的
String,
Aviator的
String是任何用单引号或者双引号括起来的字符序列,
String可以比较大小(基于
unicode顺序),
可以参与正则匹配, 可以与任何对象相加, 任何对象与
String相加结果为
String。
String中也可以有转义字符,如
\n、\\、\'等。
AviatorEvaluator.execute(" 'a\"b' "); // 字符串 a"b AviatorEvaluator.execute(" \"a\'b\" "); // 字符串 a'b AviatorEvaluator.execute(" 'hello ' + 3 "); // 字符串 hello 3 AviatorEvaluator.execute(" 'hello '+ unknow "); // 字符串 hello null
exec 方法
Aviator 2.2 开始新增加一个exec方法,
可以更方便地传入变量并执行, 而不需要构造
env这个
map了:
String name = "dennis"; AviatorEvaluator.exec(" 'hello ' + yourName ", name); // hello dennis
只要在
exec中按照变量在表达式中的出现顺序传入变量值就可以执行,
不需要构建
Map了。
调用函数
Aviator 支持函数调用, 函数调用的风格类似 lua, 下面的例子获取字符串的长度:AviatorEvaluator.execute("string.length('hello')"); // 5
string.length('hello')是一个函数调用,
string.length是一个函数,
'hello'是调用的参数。
再用
string.substring来截取字符串:
AviatorEvaluator.execute("string.contains(\"test\", string.substring('hello', 1, 2))"); // true
通过
string.substring('hello', 1, 2)获取字符串
'e',
然后通过函数
string.contains判断
e是否在
'test'中。可以看到,
函数可以嵌套调用。
Aviator 的内置函数列表请看后面。
自定义函数
Aviator 除了内置的函数之外,还允许用户自定义函数,只要实现com.googlecode.aviator.runtime.type.AviatorFunction接口,
并注册到
AviatorEvaluator即可使用.
AviatorFunction接口十分庞大,
通常来说你并不需要实现所有的方法, 只要根据你的方法的参 数个数, 继承
AbstractFunction类并
override相应方法即可。
可以看一个例子,我们实现一个
add函数来做数值的相加:
public class TestAviator { public static void main(String[] args) { //注册函数 AviatorEvaluator.addFunction(new AddFunction()); System.out.println(AviatorEvaluator.execute("add(1, 2)")); // 3.0 System.out.println(AviatorEvaluator.execute("add(add(1, 2), 100)")); // 103.0 } } class AddFunction extends AbstractFunction { @Override public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) { Number left = FunctionUtils.getNumberValue(arg1, env); Number right = FunctionUtils.getNumberValue(arg2, env); return new AviatorDouble(left.doubleValue() + right.doubleValue()); } public String getName() { return "add"; } }
注册函数通过
AviatorEvaluator.addFunction方法,
移除可以通过
removeFunction。
编译表达式
上面提到的例子都是直接执行表达式, 事实上 Aviator 背后都帮你做了编译并执行的工作。 你可以自己先编译表达式, 返回一个编译的结果, 然后传入不同的env来复用编译结果,
提高性能, 这是更推荐的使用方式:
public class TestAviator { public static void main(String[] args) { String expression = "a-(b-c)>100"; // 编译表达式 Expression compiledExp = AviatorEvaluator.compile(expression); Map<String, Object> env = new HashMap<String, Object>(); env.put("a", 100.3); env.put("b", 45); env.put("c", -199.100); // 执行表达式 Boolean result = (Boolean) compiledExp.execute(env); System.out.println(result); // false } }
通过
compile方法可以将表达式编译成
Expression的中间对象,
当要执行表达式的时候传入
env并调用
Expression的
execute方法即可。
表达式中使用了括号来强制优先级, 这个例子还使用了
>用于比较数值大小,
比较运算符
!=、==、>、>=、<、<=不仅可以用于数值,
也可以用于
String、Pattern、Boolean等等,
甚至是任何用户传入的两个都实现了
java.lang.Comparable接口的对象之间。
编译后的结果你可以自己缓存, 也可以交给 Aviator 帮你缓存,
AviatorEvaluator内部有一个全局的缓存池,
如果你决定缓存编译结果, 可以通过:
public static Expression compile(String expression, boolean cached)
将
cached设置为
true即可,
那么下次编译同一个表达式的时候将直接返回上一次编译的结果。
使缓存失效通过:
public static void invalidateCache(String expression)
方法。
访问数组和集合
可以通过中括号去访问数组和java.util.List对象,
可以通过
map.key访问
java.util.Map中
key对应的
value,
一个例子:
public static void main(String[] args) { final List<String> list = new ArrayList<String>(); list.add("hello"); list.add(" world"); final int[] array = new int[3]; array[0] = 0; array[1] = 1; array[2] = 3; final Map<String, Date> map = new HashMap<String, Date>(); map.put("date", new Date()); Map<String, Object> env = new HashMap<String, Object>(); env.put("list", list); env.put("array", array); env.put("mmap", map); System.out.println(AviatorEvaluator.execute("list[0]+list[1]", env)); // hello world System.out.println(AviatorEvaluator.execute("'array[0]+array[1]+array[2]=' + (array[0]+array[1]+array[2])", env)); // array[0]+array[1]+array[2]=4 System.out.println(AviatorEvaluator.execute("'today is ' + mmap.date ", env)); // today is Wed Feb 24 17:31:45 CST 2016 }
三元操作符
Aviator 不提供if else语句,
但是提供了三元操作符
?:用于条件判断,使用上与
java 没有什么不同:
AviatorEvaluator.exec("a>0? 'yes':'no'", 1); // yes
Aviator 的三元表达式对于两个分支的结果类型并不要求一致,可以是任何类型,这一点与 java 不同。
正则表达式匹配
Aviator 支持类 Ruby 和 Perl 风格的表达式匹配运算,通过=~操作符,
如下面这个例子匹配 email 并提取用户名返回:
public static void main(String[] args) { String email = "killme2008@gmail.com"; Map<String, Object> env = new HashMap<String, Object>(); env.put("email", email); String username = (String) AviatorEvaluator.execute("email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1 : 'unknow' ", env); System.out.println(username); // killme2008 }
/([\\w0-8]+@\\w+[\\.\\w+]+)/通过
=~操作符来匹配,结果为一个
Boolean类
型, 因此可以用于三元表达式判断,匹配成功的时候返回
$1,指代正则表达式的分组
1,也就是用户名,否则返回
unknown。
Aviator 在表达式级别支持正则表达式,通过
//括起来的字符序列构成一个正则表达式,正则表
达式可以用于匹配(作为
=~的右操作数)、比较大小,匹配仅能与字符串进行匹配。匹配成功后,
Aviator 会自动将匹配成功的分组放入
$num的变量中,其中
$0指代整个匹配的字符串,而
$1表示第一个分组,以此类推。
Aviator 的正则表达式规则跟 Java 完全一样,因为内部其实就是使用
java.util.regex.Pattern做编译的。
变量的语法糖
Aviator 有个方便用户使用变量的语法糖, 当你要访问变量a中的某个属性
b,
那么你可以通过
a.b访问到, 更进一步,
a.b.c将访问变量
a的
b属性中的
c属性值,
推广开来也就是说 Aviator 可以将变量声明为嵌套访问的形式。
TestAviator类符合
JavaBean规范,
并且是
public的,我们就可以使用语法糖:
public class TestAviator { int i; float f; Date date; // 构造方法 public TestAviator(int i, float f, Date date) { this.i = i; this.f = f; this.date = date; } // getter and setter public static void main(String[] args) { TestAviator foo = new TestAviator(100, 3.14f, new Date()); Map<String, Object> env = new HashMap<String, Object>(); env.put("foo", foo); System.out.println(AviatorEvaluator.execute("'foo.i = '+foo.i", env)); // foo.i = 100 System.out.println(AviatorEvaluator.execute("'foo.f = '+foo.f", env)); // foo.f = 3.14 System.out.println(AviatorEvaluator.execute("'foo.date.year = '+(foo.date.year+1990)", env)); // foo.date.year = 2106 } }
nil 对象
nil是 Aviator 内置的常量,类似
java 中的
null,表示空的值。
nil跟
null不同的在于,在
java 中
null只能使用在
==、!=的比较运算符,而
nil还可以使用
>、>=、<、<=等比较运算符。
Aviator 规定,任何对象都比
nil大除了
nil本身。用户传入的变量如果为
null,将自动以
nil替代。
AviatorEvaluator.execute("nil == nil"); //true AviatorEvaluator.execute(" 3> nil"); //true AviatorEvaluator.execute(" true!= nil"); //true AviatorEvaluator.execute(" ' '>nil "); //true AviatorEvaluator.execute(" a==nil "); //true, a 是 null
nil与
String相加的时候,跟
java 一样显示为
null
日期比较
Aviator 并不支持日期类型,如果要比较日期,你需要将日期写字符串的形式,并且要求是形如 “yyyy-MM-dd HH:mm:ss:SS”的字符串,否则都将报错。 字符串跟java.util.Date比较的时候将自动转换为
Date对象进行比较:
public static void main(String[] args) { Map<String, Object> env = new HashMap<String, Object>(); final Date date = new Date(); String dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS").format(date); env.put("date", date); env.put("dateStr", dateStr); Boolean result = (Boolean) AviatorEvaluator.execute("date==dateStr", env); System.out.println(result); // true result = (Boolean) AviatorEvaluator.execute("date > '2010-12-20 00:00:00:00' ", env); System.out.println(result); // true result = (Boolean) AviatorEvaluator.execute("date < '2200-12-20 00:00:00:00' ", env); System.out.println(result); // true result = (Boolean) AviatorEvaluator.execute("date==date ", env); System.out.println(result); // true }
也就是说
String除了能跟
String比较之外,还能跟
nil和
java.util.Date对象比较。
大数计算和精度
从 2.3.0 版本开始,aviator 开始支持大数字计算和特定精度的计算, 本质上就是支持java.math.BigInteger和
java.math.BigDecimal两种类型,
这两种类型在 aviator 中简称 为
big int和
decimal类型。
类似
99999999999999999999999999999999这样的数字在
Java 语言里是没办法编译通过 的, 因为它超过了
Long类型的范围,
只能用
BigInteger来封装。但是
aviator 通过包装,可 以直接支持这种大整数的计算,例如:
public static void main(String[] args) { System.out.println(AviatorEvaluator.exec("99999999999999999999999999999999 + 99999999999999999999999999999999")); }
结果为类型
big int的:
199999999999999999999999999999998
字面量表示
big int和
decimal的表示与其他数字不同,两条规则:
以大写字母
N为后缀的整数都被认为是
big int,如
1N,2N,9999999999999999999999N等,
都是
big int类型。
超过
long范围的整数字面量都将自动转换为
big int类型。
以大写字母
M为后缀的数字都被认为是
decimal,
如
1M,2.222M, 100000.9999M等,
都是
decimal类型。
用户也可以通过变量传入这两种类型来参与计算。
运算
big int和
decimal的运算,跟其他数字类型
long,double没有什么区别,操作符仍然是一样的。
aviator重载了基本算术操作符来支持这两种新类型:
public static void main(String[] args) { Object rt = AviatorEvaluator.exec("9223372036854775807100.356M * 2"); System.out.println(rt + " " + rt.getClass()); // 18446744073709551614200.712 class java.math.BigDecimal rt = AviatorEvaluator.exec("92233720368547758074+1000"); System.out.println(rt + " " + rt.getClass()); // 92233720368547759074 class java.math.BigInteger BigInteger a = new BigInteger(String.valueOf(Long.MAX_VALUE) + String.valueOf(Long.MAX_VALUE)); BigDecimal b = new BigDecimal("3.2"); BigDecimal c = new BigDecimal("9999.99999"); rt = AviatorEvaluator.exec("a+10000000000000000000", a); System.out.println(rt + " " + rt.getClass()); // 92233720368547758089223372036854775807 class java.math.BigInteger rt = AviatorEvaluator.exec("b+c*2", b, c); System.out.println(rt + " " + rt.getClass()); // 20003.19998 class java.math.BigDecimal rt = AviatorEvaluator.exec("a*b/c", a, b, c); System.out.println(rt + " " + rt.getClass()); // 2.951479054745007313280155218459508E+34 class java.math.BigDecimal }
类型转换和提升
当big int或者
decimal和其他类型的数字做运算的时候,按照
long < big int < decimal < double的规则做提升, 也就是说运算的数字如果类型不一致, 结果的类型为两者之间更“高”的类型。例如:
1 + 3N, 结果为
big int的
4N
1 + 3.1M,结果为
decimal的
4.1M
1N + 3.1M,结果为
decimal的
4.1M
1.0 + 3N,结果为
double的
4.0
1.0 + 3.1M,结果为
double的
4.1
decimal 的计算精度
Java 的java.math.BigDecimal通过
java.math.MathContext支持特定精度的计算,任何涉及到金额的计算都应该使用
decimal类型。
默认 Aviator 的计算精度为
MathContext.DECIMAL128,你可以自定义精度,
通过:
AviatorEvaluator.setMathContext(MathContext.DECIMAL64);
即可设置,更多关于
decimal的精度问题请看
java.math.BigDecimal的
javadoc 文档。
强大的 seq 库
aviator 拥有强大的操作集合和数组的 seq库。整个库风格类似函数式编程中的高阶函数。在
aviator 中, 数组以及
java.util.Collection下的子类都称为
seq,可以直接利用
seq库进行遍历、过滤和聚合等操作。
例如,假设我有个
list:
public static void main(String[] args) { Map<String, Object> env = new HashMap<String, Object>(); ArrayList<Integer> list = new ArrayList<Integer>(); list.add(3); list.add(20); list.add(10); env.put("list", list); Object result = AviatorEvaluator.execute("count(list)", env); System.out.println(result); // 3 result = AviatorEvaluator.execute("reduce(list,+,0)", env); System.out.println(result); // 33 result = AviatorEvaluator.execute("filter(list,seq.gt(9))", env); System.out.println(result); // [10, 20] result = AviatorEvaluator.execute("include(list,10)", env); System.out.println(result); // true result = AviatorEvaluator.execute("sort(list)", env); System.out.println(result); // [3, 10, 20] AviatorEvaluator.execute("map(list,println)", env); }
我们可以:
求长度:
count(list)
求和:
reduce(list,+,0),
reduce函数接收三个参数,第一个是
seq,第二个是聚合的函数,如
+等,第三个是聚合的初始值
过滤:
filter(list,seq.gt(9)),
过滤出
list中所有大于
9的元素并返回集合;
seq.gt函数用于生成一个谓词,表示大于某个值
判断元素在不在集合里:
include(list,10)
排序:
sort(list)
遍历整个集合:
map(list,println),
map接受的第二个函数将作用于集合中的每个元素,这里简单地调用
println打印每个元素
两种运行模式
默认 AviatorEvaluator以执行速度优先:
AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL);
你可以修改为编译速度优先,这样不会做编译优化:
AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);
调试信息
从 2.1.1.版本开始,Aviator允许设置输出每个表达式生成的字节码,只要设置trace为
true即可:
AviatorEvaluator.setTrace(true);
方便用户做跟踪和调试。默认是输出到标准输出,你可以改变输出指向:
AviatorEvaluator.setTraceOutputStream(new FileOutputStream(new File("aviator.log")));
语法手册
下面是 Aviator 详细的语法规则定义。
数据类型
Number类型: 数字类型,支持四种类型,分别是
long,double,java.math.BigInteger(简称 big int)和
java.math.BigDecimal(简 称 decimal),规则如下:
任何以大写字母
N结尾的整数都被认为是
big int
任何以大写字母
M结尾的数字都被认为是
decimal
其他的任何整数都将被转换为
Long
其他任何浮点数都将被转换为
Double
超过
long范围的整数字面量都将自动转换为
big int类型
其中
big int和
decimal是
2.3.0 版本开始引入的。数字还支持十六进制(以
0x或者
0X开头的数字),
以及科学计数法,如
1e-3等。 不支持其他进制。
String类型: 字符串类型,单引号或者双引号括起来的文本串,如
'hello world', 变量如果传入的是
String或者
Character也将转为
String类型
Bool类型: 常量
true和
false,表示真值和假值,与
java 的
Boolean.TRUE和
Boolean.False对应
Pattern类型: 正则表达式,
以
//括起来的字符串,如
/\d+/,内部
实现为
java.util.Pattern
变量类型: 与 Java 的变量命名规则相同,变量的值由用户传入
nil类型: 常量
nil,类似
java 中的
null,但是
nil比较特殊,
nil不仅可以参与
==、!=的比较,
也可以参与
>、>=、<、<=的比较,Aviator
规定任何类型都大于
nil除了
nil本身,
nil==nil返回
true。
用户传入的变量值如果为
null,那么也将作为
nil处理,
nil打印为
null
操作符
算术运算符
Aviator 支持常见的算术运算符,包括+ - * / %五个二元运算符,和一元运算符
-(负)。其中
- * / %和一元的
-仅能作用于
Number类型。
+不仅能用于
Number类型,还可以用于
String的相加,或者字符串与其他对象的相加。
Aviator 规定,任何类型与
String相加,结果为
String。
逻辑运算符
Avaitor 的支持的逻辑运算符包括,一元否定运算符!,以及逻辑与的
&&,逻辑或的
||。逻辑运算符的操作数只能为
Boolean。
&&和
||都执行短路规则。
关系运算符
Aviator 支持的关系运算符包括<, <=, >, >=以及
==和
!=。
关系运算符可以作用于
Number之间、
String之间、
Pattern之间、
Boolean之间、变量之间以及其他类型与
nil之间的关系比较,
不同类型除了
nil之外不能相互比较。
位运算符
Aviator 支持所有的 Java 位运算符,包括&, |, ^, ~, >>, <<, >>>。
匹配运算符
匹配运算符=~用于
String和
Pattern的匹配,它的左操作数必须为
String,右操作数必须为
Pattern。
匹配成功后,
Pattern的分组将存于变量
$num,
num为分组索引。
三元运算符
Aviator 没有提供if else语句,但是提供了三元运算符
?:,形式为
bool ? exp1: exp2。 其中
bool必须为
Boolean类型的表达式,
而
exp1和
exp2可以为任何合法的
Aviator 表达式,并且不要求
exp1和
exp2返回的结果类型一致。
内置函数
函数名称 | 说明 |
---|---|
sysdate() | 返回当前日期对象 java.util.Date |
rand() | 返回一个介于 0-1 的随机数,double 类型 |
print([out],obj) | 打印对象,如果指定 out,向 out 打印, 否则输出到控制台 |
println([out],obj) | 与 print 类似,但是在输出后换行 |
now() | 返回 System.currentTimeMillis |
long(v) | 将值的类型转为 long |
double(v) | 将值的类型转为 double |
str(v) | 将值的类型转为 string |
date_to_string(date,format) | 将 Date 对象转化化特定格式的字符串,2.1.1 新增 |
string_to_date(source,format) | 将特定格式的字符串转化为 Date 对 象,2.1.1 新增 |
string.contains(s1,s2) | 判断 s1 是否包含 s2,返回 Boolean |
string.length(s) | 求字符串长度,返回 Long |
string.startsWith(s1,s2) | s1 是否以 s2 开始,返回 Boolean |
string.endsWith(s1,s2) | s1 是否以 s2 结尾,返回 Boolean |
string.substring(s,begin[,end]) | 截取字符串 s,从 begin 到 end,如果忽略 end 的话,将从 begin 到结尾,与 java.util.String.substring 一样。 |
string.indexOf(s1,s2) | java 中的 s1.indexOf(s2),求 s2 在 s1 中 的起始索引位置,如果不存在为-1 |
string.split(target,regex,[limit]) | Java 里的 String.split 方法一致,2.1.1 新增函数 |
string.join(seq,seperator) | 将集合 seq 里的元素以 seperator 为间隔 连接起来形成字符串,2.1.1 新增函数 |
string.replace_first(s,regex,replacement) | Java 里的 String.replaceFirst 方法, 2.1.1 新增 |
string.replace_all(s,regex,replacement) | Java 里的 String.replaceAll 方法 , 2.1.1 新增 |
math.abs(d) | 求 d 的绝对值 |
math.sqrt(d) | 求 d 的平方根 |
math.pow(d1,d2) | 求 d1 的 d2 次方 |
math.log(d) | 求 d 的自然对数 |
math.log10(d) | 求 d 以 10 为底的对数 |
math.sin(d) | 正弦函数 |
math.cos(d) | 余弦函数 |
math.tan(d) | 正切函数 |
map(seq,fun) | 将函数 fun 作用到集合 seq 每个元素上, 返回新元素组成的集合 |
filter(seq,predicate) | 将谓词 predicate 作用在集合的每个元素 上,返回谓词为 true 的元素组成的集合 |
count(seq) | 返回集合大小 |
include(seq,element) | 判断 element 是否在集合 seq 中,返回 boolean 值 |
sort(seq) | 排序集合,仅对数组和 List 有效,返回排 序后的新集合 |
reduce(seq,fun,init) | fun 接收两个参数,第一个是集合元素, 第二个是累积的函数,本函数用于将 fun 作用在集合每个元素和初始值上面,返回 最终的 init 值 |
seq.eq(value) | 返回一个谓词,用来判断传入的参数是否跟 value 相等,用于 filter 函数,如filter(seq,seq.eq(3)) 过滤返回等于3 的元素组成的集合 |
seq.neq(value) | 与 seq.eq 类似,返回判断不等于的谓词 |
seq.gt(value) | 返回判断大于 value 的谓词 |
seq.ge(value) | 返回判断大于等于 value 的谓词 |
seq.lt(value) | 返回判断小于 value 的谓词 |
seq.le(value) | 返回判断小于等于 value 的谓词 |
seq.nil() | 返回判断是否为 nil 的谓词 |
seq.exists() | 返回判断不为 nil 的谓词 |
相关链接
GitHub上的资料
相关文章推荐
- AlertDialog单选、多选对话框详解
- NSBundle pathForResource is NULL 取不到值
- LeetCode 102. Binary Tree Level Order Traversal
- Java进阶(二十三)java中long类型转换为int类型
- Java进阶(二十三)java中long类型转换为int类型
- hibernate笔记--单向多对一映射方法
- 最佳实践: 勿在 Servlet 中实现 SingleThreadModel
- Win32多线程编程学习心得
- POJ2528Mayor's posters(离散化 + 线段树)
- overflow:hidden与margin:0 auto之间的冲突
- js循环使用
- Linux搭建
- CNN中感受野的计算
- 基本sql语句
- ubutnu 14.04LTS 安装opencv2.4
- string类型的查找
- jQuery--加一行减一行
- LeetCode 173. Binary Search Tree Iterator
- js限制input只能输入有效的数字,有且只有一个小数点,第一个不能为小数点-备
- javascript、js计算两个日期之间的天数