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,讓我一度陷入困境,後來多虧我們老大指點迷津,我才發現 哦原來是這樣用的,敬請期待吧。

感謝閱讀,菜鳥一枚,如有錯誤,請不吝指正,謝謝

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