jeval简述

jeval是一个数字表达式解析器,支持解析字符串,数字,布尔值和自定义函数,因为很早就已经不再更新,所以现在大部分网页上只是粗浅的认识,而且也没一个现成的api文档供大家学习。甚至jeval网站都已经找不到相关资料。
我从网上找了一篇英文介绍,以我粗浅的英语四级水平勉强翻译一下,加上我的使用心得,如有不足之处,请不吝指正。

This class is used to evaluate mathematical, string, Boolean and functional expressions. It is the main entry point into the JEval API.
The following types of expressions are supported:
mathematical Expression involving numbers. Numbers are treated as doubles, so resulting numbers will contain at least one decimal place.

jeval框架有个核心类是evaluator这个类,基本所有的功能都是围绕这个类展开,这个类主要用来解析,数字,字符串,布尔值,和函数式的表达式。这是jeval api的关键,支持下面几种类型的表达式:

  1. 包含数字的数学表达式 eg:1+3+5*6
    数字被当做double类型的数字对待,所以处理结果将包含至少一个小数点。(意思就是解析数学表达式的时候,里面的所有数字都是以double类型处理的)

string String can also be added together, compared, etc…
Boolean Expression that evaluate to true (1.0) and false (0.0).
functional Custom functions can be created or there are many Math and String functions that JEval supplies with this class.

jeval有一些内置的字符串函数,支持字符串拼接,比较,等等; 也支持布尔表达式,返回结果1.0表示true,0.0表示false ;支持自定义函数,关于自定义函数的使用我另开一篇博客。jeval提供了很多关于字符串和数学的内置函数,数学函数如sin,cos,tan,asin,acos,max.min等等,字符串函数如charat,compareto,equals等等,具体可下载jar详细学习使用

The following operators are supported:
下面的操作符是支持的:
( open parentheses 左括号
) closed parentheses 右括号
+ addition (for numbers and strings)
- subtration
* mutliplication
/ division
% modulus
+ unary plus 一元运算符,不懂看这篇博客,记得回来
- unary minus
= equal (for numbers and strings)
!= not equal (for numbers and strings)
< less than (for numbers and strings)
<= less than or equal (for numbers and strings)
greater than (for numbers and strings)
= greater than or equal (for numbers and strings)
&& boolean and
|| boolean or
! boolean not
Allows for prebuilt and custom functions. 自定义函数

大部分应该一眼就能看懂,部分运算符作注释在后面供参考

JEval already comes with many functions which represent most of the methods in the Math and String classes in the standard JDK.
Thirty-nine math and string functions come built in. See the net.sourceforge.jeval.functions.math and net.sourceforge.jeval.functions.string packages for details on these ready to use functions. You can choose to not load these functions if we you want to gain a small improvement in performance.
Functions must be followed by an open parentheses and a closed parentheses which contain any required parameters.
For more details on functions, see the Function class and the test classes.
Allows for variables.

jeval自带许多函数,实现了大多数java标准字符串和数学类库的方法,有39个数学和字符串函数,如果要使用这些函数的话,具体细节请看包目录net.sourceforge.jeval.functions.math和net.sourceforge.jeval.functions.string 。如果你想获得一个小的性能提升,你可以不加载所有这些函数。这句话我理解意思是这样的,因为jeval使用evaluator会默认加载所有函数,但是考虑到性能影响,可以不加载这些函数。关于函数的更多细节,看具体的函数类吧

Variable must be enclosed by a pound sign and open brace #{ and a closed brace }. i.e. expression = “#{a} + #{b}”
Two math variables come built in. The E and PI variables represent the same value as the Math.E and Math.PI constants in the standard Java SDK. You can choose not to load these variables.

变量必须用#和{}括起来 ,例如 表达式="#{a} + #{b}",这里意思是当你的表达式中含有变量时,你可以用#{}括起来,然后通过evaluator.set (“a”,“2”);evaluator.set (“b”,“3”);的方式实现设置值并计算表达式的值。
两个内置的数学变量,E 和 π 和java中的 Math.E and Math.PI 代表同样的值。你可以选择不加载这些变量。

Notes on expression parsing:
Spaces are ignored when parsing expressions.
The order of precedence used by this class is as follows from highest to lowest.
The expression is evaluated as one or more subexpressions. Subexpressions within open parentheses and closed parentheses are evaluated before other parts of the expression.
Inner most subexpression are evaluated first working outward.
Subexpressions at the same level are evaluated from left to right.
When evaluating expressions and subexpressions, operators are evaluated with the following precedence listed below.

表达式解析说明:

  1. 表达式解析的时候,空格是被忽略的
  2. 表达式解析的优先级顺序是从高到低
  3. 当前表达式可以作为其他表达式的一个或者多个子表达式,意思是表达式可以嵌套
  4. ()括起来的子表达式比这个表达式的其他部分先执行
  5. 最内部的子表达式首先开始向外计算
  6. 同等级的子表达式从左往右依次计算
  7. 在计算表达式和子表达式时,运算符的计算顺序如下所示:

operators with with the same precedence are evaluated from left to right.
Once the expression is parsed, Variables are replaced with their values. The evaluator has its own internal variable map that it used to resolve variable values. All of the variable related methods on the evaluator refer to this internal map. You can choose to set you own variable resolver on your evaluator instance. IF you do this, then variables resolved by your resolver will override any variables in the evaluator’s internal variable map.
Functions are then executed and replaced with their results.

  1. 同样优先级的操作符从左往右依次计算
  2. 一旦表达式被解析,变量就被他的值替换,意思就是当你的表达式被解析后,表达式里面的变量也会被设置进值
  3. jeval有自己的用来解析变量值的内部变量map,你可以选择设置你自己的变量解析器在创建的evalutor实例上,如果你这样做了,通过你自己变量解析器解析的变量将覆盖jeval原生的内置变量map
  4. 函数然后被执行,并用执行结果代替,这里我理解意思就是变量解析完设置值后,函数开始执行,最后函数会被有自己的执行结果,如果这个函数嵌套在其他函数体内,相当于这个函数被他的结果代替。

Function arguments are each inidividually evaluated as subexpressions that are comma separated. This gives you the ability to use nested functions in your expressions. You can choose not to evaluate function arguments as expressions and instead let the functions handle the arguments themselves. This in effect turns off nested expressions, unless you code nexted expression support into yours custom functions.

每个函数参数独立作为被逗号分隔的子表达式执行。这使你能够在表达式中使用嵌套函数,你可以选择不将函数参数作为表达式计算,而是让这些函数自己控制参数,这样将会无法使用嵌套函数,除非你的代码实现的自定义函数支持链式表达式。

Once all variables and functions are resolved, then the parsed expression and subexpressions are evaluated according to operator precedence.
Operator precedence:
/+ unary plus, - unary minus, ! boolean not
/* multiplication, / division, % modulus
/+ addition, - subtraction
< less than, <= less than or equal, > greater than, >= greater than or equal
= equal, != not equal
&& boolean and
|| boolean or
Function and variable names can not break any of the following rules:
can not start with a number
can not contain an operator (see the above list of operators)/li>
can not contain a quote character - single or double/li>
can not contain a brace character - open or closed/li>
can not contain one of the following special characters: #, ~ , ^ !

等所有的变量和函数解析后,这些解析的表达式和子表达式按照下面的操作符操作顺序执行:
顺序在上面就不再赘述了,ps :这些顺序没有亲测,只是照搬过来,使用的时候需要留意
函数和变量的名字不能打破以下的规则:

  1. 不能用数字开头
  2. 不能包含操作符
  3. 不能包含单引号 双引号
  4. 不能包含()
  5. 不能包含下面的特殊字符:#,~,^

Other Notes:
This class is not thread safe.
Allows for the quote character (single or double) to be specified at run time. Quote characters are required for specifying string values.
Expressions can contain different types of expressions within the same expression. However, Numeric and string types can not be mixed in a left / right oeprand pair.
An expression can be parsed before being evaluated by calling the parse() method. This may save on response time if parsing takes more than a few seconds. However, parsing is usally very fast, so this is probably not needed.

其他要注意的:
1. jeval不是线程安全的
2. jeval默认是使用单引号’ 作为引号符的,但是也允许你定义双引号为引号符,主要是用来指定字符串值

3. 可以在同一表达式中包含不同类型的表达式。但是,数字和字符串类型不能混合在左/右oeprand对中。意思大概就是不能 用加 * 实现 12 * abc之类的运算
4. 通过调用parse方法实现表达式之前表达式可以提前解析,这样可能减少表达式执行时间如果解析花时间稍微多的话,但是解析通常是非常快的,所以这个操作可能用不到

Also, if an expression does not change, it will not be parsed each time the expression is evaluated. Therefore, variables values can change and the expression can be evaluataed again without having to re-parse the expression.
Nested functions calls are supported. Nested function support can be turned off to improve performance. Custom functions can be coded to handle nested calls instead if desired.
The string used to start variables, “#{”, can not appear in an expression.

而且,如果表达式没有改变,下次调用的时候就不会被解析。因此,表达式可以在不重新解析的情况下改变变量值执行
嵌套函数是支持的,为了提升性能嵌套函数可以禁止使用。如果需要,可以使用自定义函数处理嵌套。
用于标志变量开始的字符串不能用于任何一个表达式中。

笔者碎碎念:
细读下来你会发现jeval大部分处理逻辑和我们日常处理逻辑一样的,比如运算符优先级,从左往右计算等等,好多初学者容易犯的错误是不能按照框架要求的规范实现表达式,所以会导致出现一起奇奇怪怪的错误。这个工具类大部分报错并不复杂,调试一下就会发现问题出在哪里。
可能有些人会问为啥要用这个已经很久没维护甚至都没有api文档的工具,主要是他方便二开,他可以很方便的让我们实现自己的自定义函数,而且我们可以在上面任意扩展,甚至熟悉到一定程度可以重构他的源码。看过源码你会发现这个**框架核心类就是Evaluator.**层层递归处理表达式。

这边简述基本介绍了jeval是啥,计划另开两篇博客介绍jeval的内置函数使用jeval自定义函数使用,ps: 关于jeval自定义函数实现网上的资料真的太少了,我刚学的时候找了一周多,一直没找到能给我答案的,加上没有文档api,让我一度陷入困境,后来多亏我们老大指点迷津,我才发现 哦原来是这样用的,敬请期待吧。

感谢阅读,菜鸟一枚,如有错误,请不吝指正,谢谢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章