JEXL 是 Apache 软件基金会下的一个项目,它允许你在 Java 应用程序中评估表达式。这些表达式可以是简单的算术运算,也可以是复杂的、包含方法调用和属性访问的链式操作。

核心价值:

  • 轻量级:库很小,易于集成。
  • 易于使用:语法直观,学习成本低。
  • 高性能:表达式被解析成 AST(抽象语法树)并缓存,执行效率高。
  • 与 Java 无缝集成:可以直接调用 Java 对象的方法和访问字段。

1. 语言基础要素

注释

  • 单行注释:##//
  • 多行注释:/* ... */

标识符和变量

  • 命名规则:以字母、_$开头,后可跟字母、数字、_$
  • 无效示例9v, !a99, 1$
  • Ant风格:支持点分隔变量名如 my.dotted.var

保留关键字

or, and, eq, ne, lt, gt, le, ge, div, mod, not, null, true, false, new, var, do, while, break, continue, function, return

2. 脚本和编译指示(Pragma)

脚本特性

  • 由零个或多个语句组成
  • 可包含函数定义块
  • 默认返回最后执行语句的值
  • 可使用return显式返回

编译指示

#pragma execution.option 42
#pragma jexl.options "+strict -safe"
#pragma jexl.namespace.str java.lang.String
#pragma jexl.import java.net

3. 变量声明和作用域

关键字作用域重新赋值特点
let词法块作用域允许模拟Java行为
const词法块作用域禁止常量声明
var整个脚本允许可被词法特性改变

4. 字面量类型

数值字面量

42           // 整数
42.0         // 浮点数  
42l          // 长整型
42.0d        // 双精度
42h          // BigInteger
42.0b        // BigDecimal
0x10         // 十六进制
010          // 八进制
42.0E-1      // 科学计数法

其他字面量

"hello"      // 字符串
`Hello ${user}` // 多行模板字符串
~/ABC.*/     // 正则表达式
true/false   // 布尔值
null         // 空值

集合字面量

[1, 2, 3]           // 数组
[1, 2, "three",...] // 列表
{"one", 2, "more"}  // 集合
{"one": 1, "two": 2} // 映射
1..42               // 范围

5. 运算符系统

逻辑运算符

&&, and, ||, or, !, not

比较运算符

==, !=, <, <=, >, >=
eq, ne, lt, le, gt, ge  // 文本形式
===, !==               // 严格相等

位运算符

&, |, ^, ~, <<, >>, >>>

特殊运算符

condition ? trueVal : falseVal  // 三元
value ?: defaultVal            // 简写三元
left ?? right                  // 空值合并
=~, !~                        // 正则匹配
=^, !^                        // 开头匹配
=$, !$                        // 结尾匹配

副作用运算符

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=

6. 函数系统

内置函数

empty(arg)          // 空值检查
size(arg)           // 大小计算
new(className, args) // 对象创建

函数定义

var fun = function(x, y) { x + y }
var fun = (x, y) -> { x + y }
var fun = x -> x * x           // 单参数简写

命名空间函数

math:cosinus(23.0)  // 命名空间调用

7. 访问操作符

属性访问

foo.bar            // 点号访问
foo['bar']         // 方括号访问
foo?.bar           // 安全导航
foo.'b a r'        // 带空格属性
cal.`${dd.year}-${dd.month}-${dd.day}` // 动态属性

集合访问

array[0]           // 数组访问
list[0]            // 列表访问  
map['key']         // 映射访问
x?[y]?[z]          // 安全数组访问

8. 控制结构

条件语句

if (condition) {
    // 代码块
} else {
    // 代码块
}

循环语句

for (let item : collection) { }
for (let i = 0; i < 10; i++) { }
while (condition) { }
do { } while (condition)

流程控制

continue;    // 跳过当前迭代
break;       // 退出循环
return value; // 返回值
throw exception; // 抛出异常

9. 异常处理

try {
    // 可能出错的代码
} catch (let e) {
    // 异常处理
} finally {
    // 清理代码
}

// 资源管理
try(let f = open("file")) {
    // 使用资源
}

10. 注解系统

@synchronized(x) x.someMethod()
@lenient @silent x.someMethod()
@parallel(pool, 8) x.someMethod()
注解主要作用适用场景
@synchronized线程同步共享资源访问、计数器操作
@lenient抑制软异常嵌套属性访问、可选方法调用
@silent抑制所有异常容错操作、清理任务
@parallel并行执行大数据处理、耗时计算

关键特性总结

  1. 类型系统:支持强类型和动态类型
  2. 安全性:提供安全导航和空值处理
  3. 扩展性:支持运算符重载和自定义函数
  4. Java集成:无缝与Java对象和方法交互
  5. 函数式特性:支持lambda表达式和闭包
  6. 集合操作:丰富的集合字面量和操作符
  7. 错误处理:完整的异常处理机制
  8. 元编程:通过注解和编译指示支持元编程

JEXL提供了一个强大而灵活的表达语言,既保持了与Java的良好集成,又提供了脚本语言的简洁性和动态特性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐