Aviator介绍

article/2025/10/24 0:29:34

Aviator简介

Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢?

Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上依赖包也才 537K,不算依赖包的话只有 70K; 当然, Aviator的语法是受限的, 它不是一门完整的语言, 而只是语言的一小部分集合。

其次, Aviator的实现思路与其他轻量级的求值器很不相同, 其他求值器一般都是通过解释的方式运行, 而Aviator则是直接将表达式编译成 JVM 字节码, 交给 JVM 去执行。简单来说, Aviator的定位是介于 Groovy 这样的重量级脚本语言和 IKExpression 这样的轻量级表达式引擎之间。

AviatorScript 是一门高性能、轻量级寄宿于 JVM (包括 Android 平台)之上的脚本语言。

Aviator 使用场景

  1. 常见的公式计算
  2. 数据处理转换
  3. 数据核对
  4. 工作流逻辑判定
  5. 鉴权校验等等
  6. 动态脚本控制
  7. 规则判断及规则引擎

Aviator 的特性:

  1. 支持数字、字符串、正则表达式、布尔值、正则表达式等基本类型,完整支持所有 Java 运算符及优先级等。
  2. 函数是一等公民,支持闭包和函数式编程。
  3. 内置 bigint/decmal 类型用于大整数和高精度运算,支持运算符重载得以让这些类型使用普通的算术运算符 +-*/ 参与运算。
  4. 完整的脚本语法支持,包括多行数据、条件语句、循环语句、词法作用域和异常处理等。
  5. 函数式编程结合 Sequence 抽象,便捷处理任何集合。
  6. 轻量化的模块系统。
  7. 多种方式,方便地调用 Java 方法,完整支持 Java 脚本 API(方便从 Java 调用脚本)。
  8. 丰富的定制选项,可作为安全的语言沙箱和全功能语言使用。
  9. 轻量化,高性能,ASM 模式下通过直接将脚本翻译成 JVM 字节码,解释模式可运行于 Android 等非标 Java 平台
  10. 语法糖支持a.b.c.d
  11. 支持script执行


Aviator的设计是通过编译并动态生成字节码的方式将表达式编译成一个类,然后反射执行这个类

AviatorScript 文档: AviatorScript 文档 · 语雀

源码:GitHub - killme2008/aviatorscript: A high performance scripting language hosted on the JVM.

快速开始

推荐使用版本 5.2.6 及以上

1、POM.XML中引入AVIATOR依赖

  <dependency><groupId>com.googlecode.aviator</groupId><artifactId>aviator</artifactId><version>5.2.6</version></dependency>

2、基本使用

public static void main(String[] args) {System.out.println("-----------------------------------------------------------------");System.out.println("算术表达式【1+1】: " + AviatorEvaluator.execute("1+1"));System.out.println("逻辑表达式【1==1】: " + AviatorEvaluator.execute("1==1"));System.out.println("三元表达式【1==1 ? '对' : '错'】: " + AviatorEvaluator.execute("1==1 ? '对' : '错'"));System.out.println("正则表达式: " +  AviatorEvaluator.execute("'killme@2008gmail.com'=~/([\\w0-8]+@\\w+[\\.\\w+]+)/ ? $1:'unknow'"));System.out.println("-----------------------------------------------------------------");System.out.println("函数调用【6的3次方】: " + AviatorEvaluator.execute("math.pow(6,3)"));System.out.println("求字符串长度: " +       AviatorEvaluator.execute("string.length('hello')"));System.out.println("判断字符串是否包含字符串: " +     AviatorEvaluator.execute("string.contains('hello','h')"));System.out.println("是否以子串开头: " +     AviatorEvaluator.execute("math.pow(-3,2)"));System.out.println("求n次方: " +        AviatorEvaluator.execute("math.sqrt(14.0)"));System.out.println("正弦函数: " +      AviatorEvaluator.execute("math.sin(20)"));System.out.println("-----------------------------------------------------------------");Map env = new HashMap(16);env.put("yourname","aviator");String result3 = (String)AviatorEvaluator.execute(" 'hello ' + yourname ", env);System.out.println("变量和字符串相加:"+ result3);System.out.println("-----------------------------------------------------------------");}

 执行结果

-----------------------------------------------------------------
算术表达式【1+1】: 2
逻辑表达式【1==1】: true
三元表达式【1==1 ? '对' : '错'】: 对
正则表达式: killme@2008gmail.com
-----------------------------------------------------------------
函数调用【6的3次方】: 216.0
求字符串长度: 5
判断字符串是否包含字符串: true
是否以子串开头: 9.0
求n次方: 3.7416573867739413
正弦函数: 0.9129452507276277
-----------------------------------------------------------------
变量和字符串相加:hello aviator
-----------------------------------------------------------------
 

语法介绍

1、系统函数

函数名称

说明

assert(predicate, [msg])

断言函数,当 predicate 的结果为 false 的时候抛出 AssertFailed 异常, msg 错误信息可选。

sysdate()

返回当前日期对象 java.util.Date

rand()

返回一个介于 [0, 1) 的随机数,结果为 double 类型

rand(n)

返回一个介于 [0, n) 的随机数,结果为 long 类型

cmp(x, y)

比较 x 和 y 大小,返回整数,0 表示相等, 1 表达式 x > y,负数则 x < y。

print([out],obj)

打印对象,如果指定 out 输出流,向 out 打印, 默认输出到标准输出

println([out],obj)

或者

p([out], obj)

与 print 类似,但是在输出后换行

pst([out], e);

等价于 e.printStackTrace(),打印异常堆栈,out 是可选的输出流,默认是标准错误输出

now()

返回 System.currentTimeMillis() 调用值

long(v)

将值转为 long 类型

double(v)

将值转为 double 类型

boolean(v)

将值的类型转为 boolean,除了 nil 和 false,其他都值都将转为布尔值 true。

str(v)

将值转为 string 类型,如果是 nil(或者 java null),会转成字符串 'null'

bigint(x)

将值转为 bigint 类型

decimal(x)

将值转为 decimal 类型

identity(v)

返回参数 v 自身,用于跟 seq 库的高阶函数配合使用。

type(x)

返回参数 x 的类型,结果为字符串,如 string, long, double, bigint, decimal, function 等。Java  类则返回完整类名。

is_a(x, class)

当 x 是类 class 的一个实例的时候,返回 true,例如 is_a("a", String) ,class 是类名。

is_def(x)

返回变量 x 是否已定义(包括定义为 nil),结果为布尔值

undef(x)

“遗忘”变量  x,如果变量 x 已经定义,将取消定义。

range(start, end, [step])

创建一个范围,start 到 end 之间的整数范围,不包括 end, step 指定递增或者递减步幅。

tuple(x1, x2, ...)

创建一个 Object 数组,元素即为传入的参数列表。

eval(script, [bindings], [cached])

对一段脚本文本 script 进行求值,等价于 AviatorEvaluator.execute(script, env, cached)

comparator(pred)

将一个谓词(返回布尔值)转化为 java.util.Comparator 对象,通常用于 sort 函数。

max(x1, x2, x3, ...)

取所有参数中的最大值,比较规则遵循逻辑运算符规则。

min(x1, x2, x3, ...)

取所有参数中的最小值,比较规则遵循逻辑运算符规则。

constantly(x)

用于生成一个函数,它对任意(个数)参数的调用结果 x。

2、字符串函数

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 新增

3、数学函数

math.abs(d)

求 d 的绝对值

math.round(d)

四舍五入

math.floor(d)

向下取整

math.ceil(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)

正切函数

math.atan(d)

反正切函数

math.acos(d)

反余弦函数

math.asin(d)

反正弦函数

4、语法糖

public class TestAviator1 {public static void main(String[] args) {Foo foo = new Foo(100, 3.14f, new Date());Map<String, Object> env = new HashMap<>();env.put("foo", foo);String result =(String) AviatorEvaluator.execute(" '[foo i='+ foo.i + ' f='+foo.f+' year='+(foo.date.year+1900)+ ' month='+foo.date.month +']' ",env);System.out.println("执行结果:"+result);}public static class Foo{int i;float f;Date date = new Date();public Foo(int i, float f, Date date) {super();this.i = i;this.f = f;this.date = date;}public int getI() {return i;}public float getF() {return f;}public Date getDate() {return date;}}
}
执行结果
[foo i=100 f=3.14 year=2022 month=3]

集合处理

List<Map<String,Object>> list1=new ArrayList<>();
Map<String,Object> map1=new HashMap<>();
map1.put("name","我看那水");
map1.put("address","傻吊奥迪阿萨斯短时");
list1.add(map1);
map1=new HashMap<>();
map1.put("name","奥斯卡");
map1.put("address","地方进去恢复期计划和");
list1.add(map1);List<Map<String,Object>> list=new ArrayList<>();Map<String,Object> map=new HashMap<>();
map.put("coco",list1);
map.put("flag","收到货后");
list.add(map);
map=new HashMap<>();
map.put("coco",list1);
map.put("flag","爱莎");
list.add(map);Map<String,Object> env=new HashMap<>();
env.put("data",list);System.out.println( AviatorEvaluator.execute("#data.[1].flag", env, true));System.out.println( AviatorEvaluator.execute("#data.[0].coco.[0].name", env, true));

 执行结果

爱莎
我看那水

5、自定义函数

/*** 判断函数** @author carson deng* @data 2021/08/06*/
public class IfFunction extends AbstractFunction {/*** IF(bool,A,B)** @param env  数据源* @param arg1 条件值* @param arg2 值1* @param arg3 值2* @return*/@Overridepublic AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {Boolean flag = FunctionUtils.getBooleanValue(arg1, env);return AviatorRuntimeJavaType.valueOf(flag ? arg2.getValue(env) : arg3.getValue(env));}/*** IF(bool,rule,A,B)** @param env  数据源* @param arg1 条件值* @param arg2 KEY对应关系数据 target* @param arg3 规则对象1  MAP 对象* @param arg4 规则对象2  MAP 对象* @return*/@Overridepublic AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4) {Boolean flag = FunctionUtils.getBooleanValue(arg1, env);Map<String, Object> target = (Map<String, Object>) FunctionUtils.getJavaObject(arg2, env);Map<String, Object> rule;if (flag) {rule = (Map<String, Object>) FunctionUtils.getJavaObject(arg3, env);} else {rule = (Map<String, Object>) FunctionUtils.getJavaObject(arg4, env);}Map<String, Object> result = new HashMap<>(target.size());for (String key : rule.keySet()) {result.put(key, target.get(rule.get(key)));}return AviatorRuntimeJavaType.valueOf(result);}/*** 函数名称** @return*/@Overridepublic String getName() {return "fpx.if";}
}

使用自定义函数

      //自定义函数执行AviatorEvaluator.addFunction(new IFFunction());Map env1 = new HashMap(16);env.put("yourname","aviator");String result4 = (String)AviatorEvaluator.execute("IF(yourname=='aviator','我是aviator','我不是aviator')", env);System.out.println("自定义函数:"+ result4);

执行结果

自定义函数:我是aviator

6、调用 Java 类方法和 Function Missing

默认情况下, aviator 能调用的函数列表是受限的,这是基于安全和控制的角度考虑,不允许表达式调用任意方法。

如果你想调用某个对象的 java 方法,aviator 提供了下列两种方式:

  • 自定义函数包装下,比较推荐的方式,可以避免反射。
  • 导入方法作为自定义函数,基于反射的方式自动导入和调用,性能相对较差一些(JDK 8 上大概有 3 倍左右的差距)
private static class TestFunctionMissing implements FunctionMissing {@Overridepublic AviatorObject onFunctionMissing(final String name, final Map<String, Object> env,final AviatorObject... args) {// 当实现并设置了该处理器后,没有找到的函数调用都将调用该处理器执行System.out.println("Function not found, name=" + name + ", env=" + env + ", args=" + Arrays.toString(args));return FunctionUtils.wrapReturn(name);}}public static void main(final String[] args) {// Set function missing handler.AviatorEvaluator.setFunctionMissing(new TestFunctionMissing());System.out.println(AviatorEvaluator.execute("test(1,2,3)"));System.out.println(AviatorEvaluator.execute("not_found(1,2,3)"));}

  • 性能相比自定义函数较差,接近 3 倍的差距,原因也是反射。
  • 无法调用静态方法,静态方法调用仍然需要采用其他两种方式。
  • 如果第一个参数为 null,无法找出方法,因为没有对象  class 信息。

函数加载java静态方法

       //调用java静态方法
AviatorEvaluator.addStaticFunctions("str", StringUtils.class);
System.out.println(AviatorEvaluator.execute("str.isNotBlank('hello')"));
//调用java方法
AviatorEvaluator.addInstanceFunctions("s", String.class);
System.out.println(AviatorEvaluator.execute("s.indexOf('hello','l')"));

7、调用脚本函数

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;public class InvokeScriptFunction {public static void main(final String[] args) throws Exception {ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("AviatorScript");// AviatorScript code in a StringString script = "fn hello(name) { print('Hello, ' + name); }";// evaluate scriptengine.eval(script);// javax.script.Invocable is an optional interface.// Check whether your script engine implements or not!// Note that the AviatorScript engine implements Invocable interface.Invocable inv = (Invocable) engine;// invoke the global function named "hello"inv.invokeFunction("hello", "Scripting!!" );}
}

5、SpringBoot 整合 相关配置介绍

最佳实践:最佳实践 · 语雀

/*** 初始化表达式** @author carson deng* @data 2021/08/17*/
@Configuration
public class FunctionConfig {@PostConstructpublic void init() {//      AviatorEvaluator.EVAL,默认值,以运行时的性能优先,编译会花费更多时间做优化,目前会做一些常量折叠、公共变量提取的优化。适合长期运行的表达式。 表达式经常不会变化。
//      AviatorEvaluator.COMPILE 不会做任何编译优化,牺牲一定的运行性能,适合需要频繁编译表达式的场景, 比如经常编译不同的表达式。//执行优先AviatorEvaluator.setOption(Options.OPTIMIZE_LEVEL, AviatorEvaluator.EVAL);//编译优先  你可以修改为编译速度优先,这样不会做编译优化://AviatorEvaluator.setOption(Options.OPTIMIZE_LEVEL, AviatorEvaluator.COMPILE);//打开跟踪执行 默认关闭AviatorEvaluator.setOption(Options.TRACE_EVAL, true);//启用属性访问语法时,如果未找到属性值或引发异常,返回NULL  默认值为false 设置为trueAviatorEvaluator.setOption(Options.NIL_WHEN_PROPERTY_NOT_FOUND, true);//计算精度 java.util.MathContext.DECIMAL128AviatorEvaluator.setOption(Options.MATH_CONTEXT, MathContext.DECIMAL128);//浮点数解析//是否将整型数字都解析为 BigDecimal,默认为 false,也就是不启用。在所有数字都是需要高精度计算的场景,结合 ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL 选项,可以减少一些类型转换。AviatorEvaluator.setOption(Options.ALWAYS_PARSE_INTEGRAL_NUMBER_INTO_DECIMAL, false);//解析浮点数 默认 false//是否将所有浮点数解析为 Decimal 类型,适合需要高精度运算的场景,并且不想为每个浮点数字指定 M 后缀(表示 Decimal 类型)。默认为 false 不开启。AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, false);/*** 正则分组捕获 默认为 true 开启* email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1:'unknow'* 将 email 变量中的用户名部分(@ 符号之前)匹配出来,并放到 $1变量中,如果关闭 PUT_CAPTURING_GROUPS_INTO_ENV(设置为 false),将不会将捕获的分组放入 env,也就无法获取到匹配的分组。默认为 true 开启。*/AviatorEvaluator.setOption(Options.PUT_CAPTURING_GROUPS_INTO_ENV, true);/*** 变量语法糖* 是否启用变量访问的语法糖,默认情况下 Aviator 会通过 commons-beantuils 反射访问类似 a.b.c 这样的嵌套 JavaBean 变量,或者 #list.[0].name 这样的数组(链表)中的元素。但是部分用户可能想关闭这个行为,强制都从 env 中获取这些变量值,那么就可以将该选项关闭,也就是设置为 false。默认为 true 开启。*/AviatorEvaluator.setOption(Options.ENABLE_PROPERTY_SYNTAX_SUGAR, true);/*** Env 处理* 从 4.0 开始,为了支持 lambda, aviator 引入了变量作用域 scope 的概念,本来的默认行为是不再修改用户传入的 env 对象,但是后面看到比较多的用户依赖这个行为,因此提供了这个新选项 USE_USER_ENV_AS_TOP_ENV_DIRECTLY,当为 true 的时候就会将用户传入的 env 作为最顶层的作用域 scope 来使用,并且默认为 true 启用。如果你不需要 aviator 产生副作用污染你传入的 env,这个选项更推荐设置为 false*/AviatorEvaluator.setOption(Options.USE_USER_ENV_AS_TOP_ENV_DIRECTLY, true);/*** 参数捕获 默认false*/AviatorEvaluator.setOption(Options.CAPTURE_FUNCTION_ARGS, false);/*** 循环次数控制* 限制循环语句的最大次数,这个循环包括 for 语句、 while 循环语句以及 map, filter, some 等任何涉及 sequence 遍历的高阶函数。用于限制用户传入的脚本执行循环的次数,避免死循环或者耗费大量 CPU 的场景出现。** 默认值: 0,表示无限制。* 可以设置为任意正整数,比如 5000,表示单次循环最大次数是 5000。*/AviatorEvaluator.setOption(Options.MAX_LOOP_COUNT, 0);/*** 语法特性 设置 AviatorScript 支持的语法特性集合,它接受的是一个 Set<Feature>  的集合*/AviatorEvaluator.setOption(Options.FEATURE_SET,  Feature.asSet(Feature.Assignment,Feature.ForLoop,Feature.WhileLoop,Feature.Lambda,Feature.Let));/*** 类的白名单:ALLOWED_CLASS_SET* 请注意:* ● null 表示不限制(默认值)* ● 空集合表示禁止任何 class*/AviatorEvaluator.setOption(Options.ALLOWED_CLASS_SET, (new HashSet<Object>()).add(ArrayBlockingQueue.class));//设置默认缓存表达式结果AviatorEvaluator.getInstance().setCachedExpressionByDefault(true);//设置LRU缓存AviatorEvaluator.getInstance().useLRUExpressionCache(20000);}
}

参数捕获:CAPTURE_FUNCTION_ARGS

是否捕获函数调用点的参数列表,如果启用,那么类似 func 这样的自定义函数:

func(a, b, c, 100+2)

这样的表达式,就可以在 func 内得到调用的参数列表,

@Override
public AviatorObject call(final Map<String, Object> env, final AviatorObject arg1,final AviatorObject arg2, final AviatorObject arg3, final AviatorObject arg4) {List<FunctionArgument> args = FunctionUtils.getFunctionArguments(env);......}

得到的 args 就是参数列表:

[FunctionArgument, index=0, expression="a"]
[FunctionArgument, index=1, expression="b"]
[FunctionArgument, index=2, expression="c"]
[FunctionArgument, index=3, expression="100+2"]

你可以直接从 env 中通过 __args__ 变量直接获取:

List<FunctionArgument> args = (List<FunctionArgument>)env.get("__args__");

在 lambda 表达式中也可以捕获参数列表并使用,捕获的调用参数列表存放在 __args__ 变量:

List<FunctionArgument> args = (List<FunctionArgument>) AviatorEvaluator.execute("f = lambda(a,bc, d) -> __args__ end; f(1,2,100+2)");assertEquals(3, args.size());
System.out.println(args);
assertEquals(0, args.get(0).getIndex());
assertEquals("1", args.get(0).getExpression());
assertEquals(1, args.get(1).getIndex());
assertEquals("2", args.get(1).getExpression());
assertEquals(2, args.get(2).getIndex());
assertEquals("100+2", args.get(2).getExpression());

利用这一特性,你可以在运行时对调用的参数做参数校验或者分支派发,以及对于函数调用过程做优化,例如对针对参数做结果缓存等等。不过这一特性会对性能带来稍许损失。

语法特性:FEATURE_SET

设置 AviatorScript 支持的语法特性集合,它接受的是一个 Set<Feature>  的集合,Feature 包括:

  • Assignment  赋值
  • Return  返回语句
  • If  条件语句
  • ForLoop    for 循环语句,包括 break/continue。
  • WhileLoop  while 循环语句,包括 break/continue
  • Let  局部变量定义 let 语句
  • LexicalScope  大括号定义词法作用域
  • Lambda   匿名函数 lambda 定义
  • Fn    命名函数的 fn 定义
  • InternalVars  内部变量,如 __instance__ 、 __env__ 等。
  • Module   模块系统,包括 exports 和 require/load 函数
  • ExceptionHandle  异常处理,包括 try/catch/finally/throw 语句
  • NewInstance  创建对象的 new 语法支持
  • StringInterpolation 字符串插值
  • Use 是否启用 use 语法导入 java 类到当前上下文,方便 new 或者 catch 异常类等。
  • StaticFields 是否启用静态字段直接访问,类似 Long.MAX_VALUE 等。
  • StaticMethods 是否启用静态方法直接使用(基于反射),类似 Math.abs(d) 等

你可以自定义语法特性集合:

/*** Configure engine example** @author dennis(killme2008@gmail.com)**/
public class ConfigureInstanceExample {public static void main(final String[] args) {AviatorEvaluatorInstance instance = AviatorEvaluator.newInstance();instance.setOption(Options.USE_USER_ENV_AS_TOP_ENV_DIRECTLY, false);instance.setOption(Options.FEATURE_SET,Feature.asSet(Feature.Assignment, Feature.ForLoop, Feature.WhileLoop,Feature.Lambda,Feature.Let));System.out.println(instance.execute("let square = lambda(x) -> x*2 end; for x in range(0, 10) { p(square(x)); }"));}
}

这里我们启用了赋值、循环、let 以及 lambda 语法支持,然后执行一个简单脚本。 Feature.asSet 方法方便地生成一个语法特性集合。

如果我们没有启用某个语法特性,执行引擎将报错,比如假设我们将上面的 Feature.Let 移除:

Exception in thread "main" com.googlecode.aviator.exception.UnsupportedFeatureException: Feature.Let is not enabledat com.googlecode.aviator.parser.ExpressionParser.ensureFeatureEnabled(ExpressionParser.java:138)at com.googlecode.aviator.parser.ExpressionParser.statement(ExpressionParser.java:1364)at com.googlecode.aviator.parser.ExpressionParser.statements(ExpressionParser.java:1493)at com.googlecode.aviator.parser.ExpressionParser.parse(ExpressionParser.java:920)at com.googlecode.aviator.AviatorEvaluatorInstance.innerCompile(AviatorEvaluatorInstance.java:1293)at com.googlecode.aviator.AviatorEvaluatorInstance.compile(AviatorEvaluatorInstance.java:1256)at com.googlecode.aviator.AviatorEvaluatorInstance.compile(AviatorEvaluatorInstance.java:1207)at com.googlecode.aviator.AviatorEvaluatorInstance.execute(AviatorEvaluatorInstance.java:1383)at com.googlecode.aviator.AviatorEvaluatorInstance.execute(AviatorEvaluatorInstance.java:1400)at com.googlecode.aviator.AviatorEvaluatorInstance.execute(AviatorEvaluatorInstance.java:1436)at com.googlecode.aviator.example.ConfigureInstanceExample.main(ConfigureInstanceExample.java:24)

这个选项的默认值是 Feature.getFullFeatures() ,也就是启用所有的语法特性,如果你想使用 5.0 之前的兼容模式,只启用赋值、lambda 以及内部变量,可以用 Feature.getCompatibleFeatures() 。

禁用和启用单个选项可以通过 AviatorEvaluatorInstance 的 enableFeature(feature) 和 disableFeature(feature) 方法。


http://chatgpt.dhexx.cn/article/tCkSEgTE.shtml

相关文章

西电计算机学院名誉院长,杨孟飞院士受聘为西电计科院名誉院长及讲席教授

西电新闻网讯(通讯员 陈龙)12月21日上午&#xff0c;西安电子科技大学计算机科学与技术学院名誉院长杨孟飞院士“华山学者”讲席教授及战略咨询委员会委员聘任仪式在北校区主楼Ⅱ区319会议室举行&#xff0c;校长杨宗凯、副校长王泉参加仪式。仪式由计科院执行院长崔江涛主持。…

北航计算机学院新闻,澳门理工学院代表团访问我校计算机学院

北航新闻网1月21日电(通讯员 盛浩)2019年1月16日&#xff0c;澳门理工学院副院长李雁莲教授、孙毓奇教授等一行三人到北航计算机学院就双方合作等事项进行交流。 座谈会由先进计算机应用技术教育部工程研究中心熊璋教授主持&#xff0c;计算机学院副院长胡春明副教授、中心李超…

【华人学者风采】陈晓峰 西安电子科技大学

【华人学者风采】陈晓峰&#xff0c;西安电子科技大学网络与信息安全学院副院长。研究方向包括公钥密码学、金融密码学、云计算安全、数据安全、区块链技术及应用、人工智能安全。曾获荣誉&#xff1a; 国家万人计划科技创新领军人才&#xff0c;教育部“青年长江学者” &#…

港科资讯 | 倪明选校长等出席江门“双碳”实验室揭牌暨项目签约仪式

12月7日&#xff0c;由香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09;和江门市政府发起共建的江门“双碳”实验室举行了揭牌暨项目签约仪式&#xff0c;江门双碳实验室正式启动成立。香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09…

莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

一、理解 我的理解就是巧妙的暴力&#xff0c;利用双指针以及分块思想&#xff0c;巧妙的移动双指针&#xff0c;时间复杂度可以达到O(NlogN)。 强推博客&#xff1a;写的又好又全。链接 二、套路 1、普通莫队 【1】核心代码 bool cmp(node a,node b){return belong[a.l]…

香港理工大学计算机系石杰明老师组招收全奖博士生、博士后

来源&#xff1a;AI求职 香港理工大学 香港理工大学位于中国香港特别行政区&#xff0c;QS 最新排名世界 66 位。计算机系&#xff08;Department of Computing&#xff09;USNews CS 排名 36&#xff0c;泰晤士 CS 排名 79。 石杰明博士课题组成员包括有 985/211 顶尖高校背景…

【调剂】华侨大学计算机学院计算机视觉与模式识别实验室钟必能课题组研究生招生...

点击文末的阅读原文或者公众号界面左下角的调剂信息或者公众号回复“调剂”是计算机/软件等专业的所有调剂信息集合&#xff0c;会一直更新的。 课题组主页&#xff1a;https://cst.hqu.edu.cn/info/1109/2001.htmLinkedin: https://www.linkedin.com/in/bineng-zhong-71a36674…

莫队算法思想

目录 莫队算法普通莫队方法&#xff1a;主要代码结构&#xff1a;例题&#xff1a;小B的询问例题&#xff1a;小Z的袜子奇偶化排序 带修改的莫队小结&#xff1a; 莫队算法 莫队算法是由前国家队莫涛提出的一种算法&#xff0c;主要应用在一类离线区间查询的问题中&#xff0c…

【华人学者风采】冯佳时 新加坡国立大学

【华人学者风采】冯佳时&#xff0c;新加坡国立大学ECE系助理教授。本科毕业于中国科学技术大学&#xff0c;硕士毕业于中国科学院自动化研究所&#xff0c;博士毕业于新加坡国立大学。研究兴趣包括大污染数据分析&#xff0c;在线和分布式鲁棒性学习及其在对象识别中的应用。 …

港科夜闻|央视网专访香港科大(广州)(筹)校长倪明选教授,谈香港科技大学在科研及知识转移方面成就...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、央视网专访香港科大(广州)(筹)校长倪明选教授&#xff0c;谈香港科技大学在科研及知识转移方面成就。香港科技大学(广州)(筹)校长倪明选教授接受央视网专访&#xff0c;谈香港科技大学在科研及知识转移方面取得的成就&am…

独家对话许诗军:数字化转型,最基本的是不去拒绝 |数字价值观察室(下)...

关注ITValue&#xff0c;看企业级最新鲜、最价值报道&#xff01; ▎本文摘自《云栖战略参考》&#xff0c;这本刊物由阿里云与钛媒体联合策划。目的是为了把各个行业先行者的技术探索、业务实践呈现出来&#xff0c;与思考同样问题的“数字先行者”共同探讨、碰撞&#xff0c;…

港科夜闻|香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏。2021年11月1日&#xff0c;香港科技大学(广州)(筹)校长倪明选教授等一行在北京拜访国家教育部党组书记、部长怀进鹏。 2、深圳先进院与…

特么的. 最终把 amobbs 的站长阿莫(莫进明)给回骂了一顿.

起因: 假设你居住的地方&#xff0c;要上马PX等高污染的项目&#xff0c;你会怎么做. 鼓动别人上街暴力示威与军警对抗. 自己待在家里支持怂恿. 这样的人真心猥琐! 鉴于他常常私自改动帖子, 在此截图留存. 真特么没劲. 居然以封锁别人 ID 作为别人"打不还手骂不还口…

中国计算机专业创始人,无怨无悔来时路――访计算机专业创始人吴忠明校友

哈工大报讯(研究生记者团杜&#xfffd;/文 李贵才/图)&#xff15;&#xff10;年前&#xff0c;他和他的同事创建了中国最早的计算机专业之一――哈工大计算机专业。从此&#xff0c;“哈工大计算机”作为哈工大的一张名片&#xff0c;&#xff15;&#xff10;载享誉海内外。…

史上首次,45岁计算机大牛蒋濛当选普渡大学校长!

作者丨编辑部 来源丨新智元 【导读】普渡大学史上首位华裔校长诞生&#xff01;45岁计算机大牛蒋濛当选&#xff0c;本硕博全藤校&#xff0c;产学研大满贯的他&#xff0c;此前曾屡拒其他名校。 刚刚&#xff0c;年仅45岁的华裔科学家蒋濛被任命为美国普渡大学第13任校长。 这…

港科夜闻|香港科技大学(广州)倪明选校长一行到访广东省科学技术厅,与龚国平厅长、吴世文副厅长参加交流座谈会议...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、7月21日&#xff0c;香港科技大学&#xff08;广州&#xff09;倪明选校长一行到访广东省科学技术厅&#xff0c;与龚国平厅长、吴世文副厅长参加交流座谈会议。座谈会上&#xff0c;倪明选校长介绍了香港科大&#xff0…

apktool反编译apk教程

1.准备工具 (1)apktool的下载地址:https://bitbucket.org/iBotPeaches/apktool/downloads/ 点击超链接下载最新版本 (2)apktool.bat:将下面的脚本复制到文本并保存&#xff0c;然后重命名为apktool.bat; echo off setlocal set BASENAMEapktool_ chcp 65001 2>nul >nul…

C#反编译工具Reflector.exe教程

reflector.exe是一款专业的.NET反编译软件。reflector.exe可以分析程序集并向你展示它的所有秘密。.NET 框架向全世界引入了可用来分析任何基于 .NET 的代码(无论它是单个类还是完整的程序集)的反射概念。反射还可以用来检索有关特定程序集中包含的各种类、方法和属性的信息。 …

java反编译超简单教程

第一步&#xff1a;这里是代码编译完输出.class的路径&#xff0c;有自己想要反编译的程序可以跳过这一步 第二步&#xff1a;看好路径&#xff0c;将想要反编译的class文件&#xff0c;拖到src.....main...最后的项目文件夹中 完成&#xff1a;发现dog文件已经加载在我们项目中…

android反编译修改教程,逆向教程之-反编译apk修改菜单默认设置(一)

本帖最后由 liuxiaoxin 于 2020-12-3 18:58 编辑 授人以鱼,不如授人以渔!本教程图文并茂,步骤非常详细,偏小白向,大佬请自觉屏蔽。 使用工具:MT管理器免费版 被修改的软件:Apktool M_v2.4.1 如果想跟着教程一起实操,感受一下反编译带来的乐趣,修改成功之后油然而生的成…