真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JAVA規(guī)則引擎簡化代碼,java代碼設計原則

那位高手能把下面的java程序代碼簡化一下:

要化簡最多就是把循環(huán)改寫成一個遞歸方法,但是遞歸邏輯難以理解,運算速度又慢,不推薦

創(chuàng)新互聯(lián)公司專注于企業(yè)全網(wǎng)整合營銷推廣、網(wǎng)站重做改版、臨沭網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、HTML5、商城網(wǎng)站建設、集團公司官網(wǎng)建設、成都外貿(mào)網(wǎng)站建設公司、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為臨沭等各大城市提供網(wǎng)站開發(fā)制作服務。

另外如果把兩題全部打印出來,估計一臺微機能跑個幾分鐘,樓主確定真的想測試一下嗎

Java規(guī)則引擎如何集成

Java 規(guī)則引擎是一種嵌入在 Java 程序中的組件,它的任務是把當前提交給引擎的 Java 數(shù)據(jù)對象 ( 原料 ) 與加載在引擎中的業(yè)務規(guī)則( app )進行測試和比對,激活那些符合當前數(shù)據(jù)狀態(tài)下的業(yè)務規(guī)則,根據(jù)業(yè)務規(guī)則中聲明的執(zhí)行邏輯,觸發(fā)應用程序中對應的操作。

引言:

目前, Java 社區(qū)推動并發(fā)展了一種引人注目的新技術(shù) ——Java 規(guī)則引擎( Rule Engine )。利用它就可以在應用系統(tǒng)中分離商業(yè)決策者的商業(yè)決策邏輯和應用開發(fā)者的技術(shù)決策,并把這些商業(yè)決策放在中心數(shù)據(jù)庫或其他統(tǒng)一的地方,讓它們能在運行時可以動態(tài)地管理和修改,從而為企業(yè)保持靈活性和競爭力提供有效的技術(shù)支持。

規(guī)則引擎的原理

1 、基于規(guī)則的專家系統(tǒng)( RBES )簡介

Java 規(guī)則引擎起源于基于規(guī)則的專家系統(tǒng),而基于規(guī)則的專家系統(tǒng)又是專家系統(tǒng)的其中一個分支。專家系統(tǒng)屬于人工智能的范疇,它模仿人類的推理方式,使用試探性的方法進行推理,并使用人類能理解的術(shù)語解釋和證明它的推理結(jié)論。為了更深入地了解 Java 規(guī)則引擎,下面簡要地介紹基于規(guī)則的專家系統(tǒng)。 RBES 包括三部分:Rule Base ( knowledge base )、 Working Memory ( fact base )和 Inference Engine 。它們的結(jié)構(gòu)如下系統(tǒng)所示:

圖 1 基于規(guī)則的專家系統(tǒng)構(gòu)成

如圖 1 所示,推理引擎包括三部分:模式匹配器( Pattern Matcher )、議程( Agenda )和執(zhí)行引擎(Execution Engine )。推理引擎通過決定哪些規(guī)則滿足事實或目標,并授予規(guī)則優(yōu)先級,滿足事實或目標的規(guī)則被加入議程。模式匹配器決定選擇執(zhí)行哪個規(guī)則,何時執(zhí)行規(guī)則;議程管理模式匹配器挑選出來的規(guī)則的執(zhí)行次序;執(zhí)行引擎負責執(zhí)行規(guī)則和其他動作。

和人類的思維相對應,推理引擎存在兩者推理方式:演繹法( Forward-Chaining )和歸納法( Backward-Chaining )。演繹法從一個初始的事實出發(fā),不斷地應用規(guī)則得出結(jié)論(或執(zhí)行指定的動作)。而歸納法則是根據(jù)假設,不斷地尋找符合假設的事實。 Rete 算法是目前效率最高的一個 Forward-Chaining 推理算法,許多 Java 規(guī)則引擎都是基于 Rete 算法來進行推理計算的。

推理引擎的推理步驟如下:

(1) 將初始數(shù)據(jù)( fact )輸入 Working Memory 。

(2) 使用 PatternMatcher 比較規(guī)則庫( rule base )中的規(guī)則( rule )和數(shù)據(jù)( fact )。

(3) 如果執(zhí)行規(guī)則存在沖突( conflict ),即同時激活了多個規(guī)則,將沖突的規(guī)則放入沖突集合。

(4) 解決沖突,將激活的規(guī)則按順序放入 Agenda 。

(5) 使用執(zhí)行引擎執(zhí)行 Agenda 中的規(guī)則。重復步驟 2 至 5 ,直到執(zhí)行完畢所有 Agenda 中的規(guī)則。

上述即是規(guī)則引擎的原始架構(gòu), Java 規(guī)則引擎就是從這一原始架構(gòu)演變而來的。

2 、規(guī)則引擎相關(guān)構(gòu)件

規(guī)則引擎是一種根據(jù)規(guī)則中包含的指定過濾條件,判斷其能否匹配運行時刻的實時條件來執(zhí)行規(guī)則中所規(guī)定的動作的引擎。與規(guī)則引擎相關(guān)的有四個基本概念,為更好地理解規(guī)則引擎的工作原理,下面將對這些概念進行逐一介紹。

1) 信息元( InformationUnit )

信息元是規(guī)則引擎的基本建筑塊,它是一個包含了特定事件的所有信息的對象。這些信息包括:消息、產(chǎn)生事件的應用程序標識、事件產(chǎn)生事件、信息元類型、相關(guān)規(guī)則集、通用方法、通用屬性以及一些系統(tǒng)相關(guān)信息等等。

2) 信息服務( InformationServices )

信息服務產(chǎn)生信息元對象。每個信息服務產(chǎn)生它自己類型相對應的信息元對象。即特定信息服務根據(jù)信息元所產(chǎn)生每個信息元對象有相同的格式,但可以有不同的屬性和規(guī)則集。需要注意的是,在一臺機器上可以運行許多不同的信息服務,還可以運行同一信息服務的不同實例。但無論如何,每個信息服務只產(chǎn)生它自己類型相對應的信息元。

3) 規(guī)則集( Rule Set )

顧名思義,規(guī)則集就是許多規(guī)則的集合。每條規(guī)則包 含一個條件過濾器 和多個動作 。一個條件過濾器可以包含多個過濾條件。條件過濾器是多個布爾表達式的組合,其組合結(jié)果仍然是一個布爾類型的。在程序運行時, 動作將會在條件過濾器值為 true 的情況下執(zhí)行。除了一般的執(zhí)行動作,還有三類比較特別的動作,它們分別是:放棄動作( Discard Action )、包含動作( Include Action )和使信息元對象內(nèi)容持久化的動作。前兩種動作類型的區(qū)別將在 2.3 規(guī)則引擎工作機制小節(jié)介紹。

4) 隊列管理器( QueueManager )

隊列管理器用來管理來自不同信息服務的信息元對象的隊列。

下面將研究規(guī)則引擎的這些相關(guān)構(gòu)件是如何協(xié)同工作的。

如圖 2 所示,處理過程分為四個階段進行:信息服務接受事件并將其轉(zhuǎn)化為信息元,然后這些信息元被傳給隊列管理器,最后規(guī)則引擎接收這些信息元并應用它們自身攜帶的規(guī)則加以執(zhí)行,直到隊列管理器中不再有信息元。

圖 2 處理過程協(xié)作圖

3 、規(guī)則引擎的工作機制

下面專門研究規(guī)則引擎的內(nèi)部處理過程。如圖 3 所示,規(guī)則引擎從隊列管理器中依次接收信息元,然后依規(guī)則的定義順序檢查信息元所帶規(guī)則集中的規(guī)則(規(guī)則已經(jīng)排隊就緒等待信息元的到來)。如圖所示,規(guī)則引擎檢查第一個規(guī)則并對其條件過濾器求值,如果值為假,所有與此規(guī)則相關(guān)的動作皆被忽略并繼續(xù)執(zhí)行下一條規(guī)則。如果第二條規(guī)則的過濾器值為真,所有與此規(guī)則相關(guān)的動作皆依定義順序執(zhí)行,執(zhí)行完畢繼續(xù)下一條規(guī)則。該信息元中的所有規(guī)則執(zhí)行完畢后,信息元將被銷毀 ,然后從隊列管理器接收下一個信息元。在這個過程中并未考慮兩個特殊動作:放棄動作( Discard Action )和包含動作( Include Action )。放棄動作如果被執(zhí)行,將會跳過其所在信息元中接下來的所有規(guī)則,并銷毀所在信息元,規(guī)則引擎繼續(xù)接收隊列管理器中的下一個信息元 ( 就是短路了 ) 。包含動作其實就是動作中包含其它現(xiàn)存規(guī)則集的動作。包含動作如果被執(zhí)行,規(guī)則引擎將暫停并進入被包含的規(guī)則集,執(zhí)行完畢后,規(guī)則引擎還會返回原來暫停的地方繼續(xù)執(zhí)行。這一過程將遞歸進行。

圖 3 規(guī)則引擎工作機制

Java 規(guī)則引擎的工作機制與上述規(guī)則引擎機制十分類似,只不過對上述概念進行了重新包裝組合。 Java 規(guī)則引擎對提交給引擎的 Java 數(shù)據(jù)對象進行檢索,根據(jù)這些對象的當前屬性值和它們之間的關(guān)系,從加載到引擎的規(guī)則集中發(fā)現(xiàn)符合條件的規(guī)則,創(chuàng)建這些規(guī)則的執(zhí)行實例。這些實例將在引擎接到執(zhí)行指令時、依照某種優(yōu)先序依次執(zhí)行。一般來講, Java 規(guī)則引擎內(nèi)部由下面幾個部分構(gòu)成:

工作內(nèi)存( Working Memory )即工作區(qū),用于存放被引擎引用的數(shù)據(jù)對象集合;

規(guī)則執(zhí)行隊列,用于存放被激活的規(guī)則執(zhí)行實例 ;

靜態(tài)規(guī)則區(qū),用于存放所有被加載的業(yè)務規(guī)則,這些規(guī)則將按照某種數(shù)據(jù)結(jié)構(gòu)組織,

當工作區(qū)中的數(shù)據(jù)發(fā)生改變后,引擎需要迅速根據(jù)工作區(qū)中的對象現(xiàn)狀,調(diào)整規(guī)則執(zhí)行隊列中的規(guī)則執(zhí)行實例。Java 規(guī)則引擎的結(jié)構(gòu)示意圖如圖 4 所示。

圖 4 Java 規(guī)則引擎工作機制

當引擎執(zhí)行時,會根據(jù)規(guī)則執(zhí)行隊列中的優(yōu)先順序逐條執(zhí)行規(guī)則執(zhí)行實例,由于規(guī)則的執(zhí)行部分可能會改變工作區(qū)的數(shù)據(jù)對象,從而會使隊列中的某些規(guī)則執(zhí)行實例因為條件改變而失效,必須從隊列中撤銷,也可能會激活原來不滿足條件的規(guī)則,生成新的規(guī)則執(zhí)行實例進入隊列。于是就產(chǎn)生了一種 “ 動態(tài) ” 的規(guī)則執(zhí)行鏈,形成規(guī)則的推理機制。這種規(guī)則的 “ 鏈式 ” 反應完全是由工作區(qū)中的數(shù)據(jù)驅(qū)動的。

任何一個規(guī)則引擎都需要很好地解決規(guī)則的推理機制 和規(guī)則條件匹配的效率問題 。規(guī)則條件匹配的效率決定了引擎的性能,引擎需要迅速測試工作區(qū)中的數(shù)據(jù)對象,從加載的規(guī)則集中發(fā)現(xiàn)符合條件的規(guī)則,生成規(guī)則執(zhí)行實例。1982 年美國卡耐基 ? 梅隆大學的 Charles L. Forgy 發(fā)明了一種叫 Rete 算法,很好地解決了這方面的問題。目前世界頂尖的商用業(yè)務規(guī)則引擎產(chǎn)品基本上都使用 Rete 算法。

詳解什么是Java規(guī)則引擎

Java規(guī)則引擎API(JSR-94)允許客戶程序使用統(tǒng)一的方式和不同廠商的規(guī)則引擎產(chǎn)品交互,一定程度上給規(guī)則引擎廠商提供了標準化規(guī)范。但其幾乎沒有定義什么是規(guī)則引擎,當然也沒有深入到規(guī)則是如何構(gòu)建和操縱的,規(guī)則調(diào)用的效用,規(guī)則與Java語言的綁定等方面。并且JSR-94在對J2EE的支持上也不足。規(guī)則語言的標準化,JSR-94的進一步的充實深化都有待研究。

Java代碼優(yōu)化有哪些常用的方法

1、 盡量指定類的final修飾符 帶有final修飾符的類是不可派生的。

在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內(nèi)聯(lián)(inline)所有的final方法(這和具體的編譯器實現(xiàn)有關(guān))。此舉能夠使性能平均提高50% 。

2、 盡量重用對象。

特別是String 對象的使用中,出現(xiàn)字符串連接情況時應用StringBuffer 代替。由于系統(tǒng)不僅要花時間生成對象,以后可能還需花時間對這些對象進行垃圾回收和處理。因此,生成過多的對象將會給程序的性能帶來很大的影響。

3、 盡量使用局部變量,調(diào)用方法時傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時變量都保存在棧(Stack)中,速度較快。

其他變量,如靜態(tài)變量、實例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。另外,依賴于具體的編譯器/JVM,局部變量還可能得到進一步優(yōu)化。請參見《盡可能使用堆棧變量》。

4、 不要重復初始化變量

默認情況下,調(diào)用類的構(gòu)造函數(shù)時, Java會把變量初始化成確定的值:所有的對象被設置成null,整數(shù)變量(byte、short、int、long)設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關(guān)鍵詞創(chuàng)建一個對象時,構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會被自動調(diào)用。

5、 在JAVA + ORACLE 的應用系統(tǒng)開發(fā)中,java中內(nèi)嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。

6、 Java 編程過程中,進行數(shù)據(jù)庫連接、I/O流操作時務必小心,在使用完畢后,即使關(guān)閉以釋放資源。

因為對這些大對象的操作會造成系統(tǒng)大的開銷,稍有不慎,會導致嚴重的后果。

7、 由于JVM的有其自身的GC機制,不需要程序開發(fā)者的過多考慮,從一定程度上減輕了開發(fā)者負擔,但同時也遺漏了隱患,過分的創(chuàng)建對象會消耗系統(tǒng)的大量內(nèi)存,嚴重時會導致內(nèi)存泄露,因此,保證過期對象的及時回收具有重要意義。

JVM回收垃圾的條件是:對象不在被引用;然而,JVM的GC并非十分的機智,即使對象滿足了垃圾回收的條件也不一定會被立即回收。所以,建議我們在對象使用完畢,應手動置成null。

8、 在使用同步機制時,應盡量使用方法同步代替代碼塊同步。

9、 盡量減少對變量的重復計算

例如:for(int i = 0;i list.size; i ++) {

}

應替換為:

for(int i = 0,int len = list.size();i len; i ++){

}

10、盡量采用lazy loading 的策略,即在需要的時候才開始創(chuàng)建。

例如: String str = “aaa”;

if(i == 1) {

list.add(str);

}

應替換為:

if(i == 1) {

String str = “aaa”;

list.add(str);

}

11、慎用異常

異常對性能不利。拋出異常首先要創(chuàng)建一個新的對象。Throwable接口的構(gòu)造函數(shù)調(diào)用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調(diào)用跟蹤信息。只要有異常被拋出,VM就必須調(diào)整調(diào)用堆棧,因為在處理過程中創(chuàng)建了一個新的對象。 異常只能用于錯誤處理,不應該用來控制程序流程。

12、不要在循環(huán)中使用:

Try {

} catch() {

}

應把其放置在最外層。

13、StringBuffer 的使用:

StringBuffer表示了可變的、可寫的字符串。

有三個構(gòu)造方法 :

StringBuffer (); //默認分配16個字符的空間

StringBuffer (int size); //分配size個字符的空間

StringBuffer (String str); //分配16個字符+str.length()個字符空間

你可以通過StringBuffer的構(gòu)造函數(shù)來設定它的初始化容量,這樣可以明顯地提升性能。

這里提到的構(gòu)造函數(shù)是StringBuffer(int length),length參數(shù)表示當前的StringBuffer能保持的字符數(shù)量。你也可以使用ensureCapacity(int minimumcapacity)方法在StringBuffer對象創(chuàng)建之后設置它的容量。首先我們看看StringBuffer的缺省行為,然后再找出一條更好的提升性能的途徑。

StringBuffer在內(nèi)部維護一個字符數(shù)組,當你使用缺省的構(gòu)造函數(shù)來創(chuàng)建StringBuffer對象的時候,因為沒有設置初始化字符長度,StringBuffer的容量被初始化為16個字符,也就是說缺省容量就是16個字符。當StringBuffer達到最大容量的時候,它會將自身容量增加到當前的2倍再加2,也就是(2*舊值+2)。如果你使用缺省值,初始化之后接著往里面追加字符,在你追加到第16個字符的時候它會將容量增加到34(2*16+2),當追加到34個字符的時候就會將容量增加到70(2*34+2)。無論何事只要StringBuffer到達它的最大容量它就不得不創(chuàng)建一個新的字符數(shù)組然后重新將舊字符和新字符都拷貝一遍――這也太昂貴了點。所以總是給StringBuffer設置一個合理的初始化容量值是錯不了的,這樣會帶來立竿見影的性能增益。StringBuffer初始化過程的調(diào)整的作用由此可見一斑。所以,使用一個合適的容量值來初始化StringBuffer永遠都是一個最佳的建議。

14、合理的使用Java類 java.util.Vector。

簡單地說,一個Vector就是一個java.lang.Object實例的數(shù)組。Vector與數(shù)組相似,它的元素可以通過整數(shù)形式的索引訪問。但是,Vector類型的對象在創(chuàng)建之后,對象的大小能夠根據(jù)元素的增加或者刪除而擴展、縮小。請考慮下面這個向Vector加入元素的例子:

Object bj = new Object();

Vector v = new Vector(100000);

for(int I=0;

I100000; I++) { v.add(0,obj); }

除非有絕對充足的理由要求每次都把新元素插入到Vector的前面,否則上面的代碼對性能不利。在默認構(gòu)造函數(shù)中,Vector的初始存儲能力是10個元素,如果新元素加入時存儲能力不足,則以后存儲能力每次加倍。Vector類就對象StringBuffer類一樣,每次擴展存儲能力時,所有現(xiàn)有的元素都要復制到新的存儲空間之中。下面的代碼片段要比前面的例子快幾個數(shù)量級:

Object bj = new Object();

Vector v = new Vector(100000);

for(int I=0; I100000; I++) { v.add(obj); }

同樣的規(guī)則也適用于Vector類的remove()方法。由于Vector中各個元素之間不能含有“空隙”,刪除除最后一個元素之外的任意其他元素都導致被刪除元素之后的元素向前移動。也就是說,從Vector刪除最后一個元素要比刪除第一個元素“開銷”低好幾倍。

假設要從前面的Vector刪除所有元素,我們可以使用這種代碼:

for(int I=0; I100000; I++)

{

v.remove(0);

}

但是,與下面的代碼相比,前面的代碼要慢幾個數(shù)量級:

for(int I=0; I100000; I++)

{

v.remove(v.size()-1);

}

從Vector類型的對象v刪除所有元素的最好方法是:

v.removeAllElements();

假設Vector類型的對象v包含字符串“Hello”。考慮下面的代碼,它要從這個Vector中刪除“Hello”字符串:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(s);

這些代碼看起來沒什么錯誤,但它同樣對性能不利。在這段代碼中,indexOf()方法對v進行順序搜索尋找字符串“Hello”,remove(s)方法也要進行同樣的順序搜索。改進之后的版本是:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(i);

這個版本中我們直接在remove()方法中給出待刪除元素的精確索引位置,從而避免了第二次搜索。一個更好的版本是:

String s = "Hello"; v.remove(s);

最后,我們再來看一個有關(guān)Vector類的代碼片段:

for(int I=0; I++;I v.length)

如果v包含100,000個元素,這個代碼片段將調(diào)用v.size()方法100,000次。雖然size方法是一個簡單的方法,但它仍舊需要一次方法調(diào)用的開銷,至少JVM需要為它配置以及清除堆棧環(huán)境。在這里,for循環(huán)內(nèi)部的代碼不會以任何方式修改Vector類型對象v的大小,因此上面的代碼最好改寫成下面這種形式:

int size = v.size(); for(int I=0; I++;Isize)

雖然這是一個簡單的改動,但它仍舊贏得了性能。畢竟,每一個CPU周期都是寶貴的。

15、當復制大量數(shù)據(jù)時,使用System.arraycopy()命令。

int[] src={1,3,5,6,7,8};

int[] dest = new int[6];

System.arraycopy(src, 0, dest, 0, 6);

src:源數(shù)組; srcPos:源數(shù)組要復制的起始位置;

dest:目的數(shù)組; destPos:目的數(shù)組放置的起始位置;

length:復制的長度.

注意:src and dest都必須是同類型或者可以進行轉(zhuǎn)換類型的數(shù)組.

16、代碼重構(gòu):增強代碼的可讀性。

public class ShopCart {

private List carts ;

public void add (Object item) {

if(carts == null) {

carts = new ArrayList();

}

crts.add(item);

}

public void remove(Object item) {

if(carts. contains(item)) {

carts.remove(item);

}

}

public List getCarts() {

//返回只讀列表

return Collections.unmodifiableList(carts);

}

//不推薦這種方式

//this.getCarts().add(item);

}

17、不用new關(guān)鍵詞創(chuàng)建類的實例

用new關(guān)鍵詞創(chuàng)建類的實例時,構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會被自動調(diào)用。但如果一個對象實現(xiàn)了Cloneable接口,我們可以調(diào)用它的clone()方法。clone()方法不會調(diào)用任何類構(gòu)造函數(shù)。

在使用設計模式(Design Pattern)的場合,如果用Factory模式創(chuàng)建對象,則改用clone()方法創(chuàng)建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現(xiàn):

public static Credit getNewCredit() {

return new Credit();

}

改進后的代碼使用clone()方法,如下所示:

private static Credit BaseCredit = new Credit();

public static Credit getNewCredit() {

return (Credit) BaseCredit.clone();

}

上面的思路對于數(shù)組處理同樣很有用。

18、乘法和除法

考慮下面的代碼:

for (val = 0; val 100000; val +=5) {

alterX = val * 8; myResult = val * 2;

}

用移位操作替代乘法操作可以極大地提高性能。下面是修改后的代碼:

for (val = 0; val 100000; val += 5) {

alterX = val 3; myResult = val 1;

}

修改后的代碼不再做乘以8的操作,而是改用等價的左移3位操作,每左移1位相當于乘以2。相應地,右移1位操作相當于除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難于理解,所以最好加上一些注釋。

19、在JSP頁面中關(guān)閉無用的會話。

一個常見的誤解是以為session在有客戶端訪問時就被創(chuàng)建,然而事實是直到某server端程序調(diào)用HttpServletRequest.getSession(true)這樣的語句時才被創(chuàng)建,注意如果JSP沒有顯示的使用 關(guān)閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對象的來歷。由于session會消耗內(nèi)存資源,因此,如果不打算使用session,應該在所有的JSP中關(guān)閉它。

對于那些無需跟蹤會話狀態(tài)的頁面,關(guān)閉自動創(chuàng)建的會話可以節(jié)省一些資源。使用如下page指令:%@ page session="false"%

20、JDBC與I/O

如果應用程序需要訪問一個規(guī)模很大的數(shù)據(jù)集,則應當考慮使用塊提取方式。默認情況下,JDBC每次提取32行數(shù)據(jù)。舉例來說,假設我們要遍歷一個5000行的記錄集,JDBC必須調(diào)用數(shù)據(jù)庫157次才能提取到全部數(shù)據(jù)。如果把塊大小改成512,則調(diào)用數(shù)據(jù)庫的次數(shù)將減少到10次。

21、Servlet與內(nèi)存使用

許多開發(fā)者隨意地把大量信息保存到用戶會話之中。一些時候,保存在會話中的對象沒有及時地被垃圾回收機制回收。從性能上看,典型的癥狀是用戶感到系統(tǒng)周期性地變慢,卻又不能把原因歸于任何一個具體的組件。如果監(jiān)視JVM的堆空間,它的表現(xiàn)是內(nèi)存占用不正常地大起大落。

解決這類內(nèi)存問題主要有二種辦法。第一種辦法是,在所有作用范圍為會話的Bean中實現(xiàn)HttpSessionBindingListener接口。這樣,只要實現(xiàn)valueUnbound()方法,就可以顯式地釋放Bean使用的資源。

另外一種辦法就是盡快地把會話作廢。大多數(shù)應用服務器都有設置會話作廢間隔時間的選項。另外,也可以用編程的方式調(diào)用會話的setMaxInactiveInterval()方法,該方法用來設定在作廢會話之前,Servlet容器允許的客戶請求的最大間隔時間,以秒計。

22、使用緩沖標記

一些應用服務器加入了面向JSP的緩沖標記功能。例如,BEA的WebLogic Server從6.0版本開始支持這個功能,Open Symphony工程也同樣支持這個功能。JSP緩沖標記既能夠緩沖頁面片斷,也能夠緩沖整個頁面。當JSP頁面執(zhí)行時,如果目標片斷已經(jīng)在緩沖之中,則生成該片斷的代碼就不用再執(zhí)行。頁面級緩沖捕獲對指定URL的請求,并緩沖整個結(jié)果頁面。對于購物籃、目錄以及門戶網(wǎng)站的主頁來說,這個功能極其有用。對于這類應用,頁面級緩沖能夠保存頁面執(zhí)行的結(jié)果,供后繼請求使用。

23、選擇合適的引用機制

在典型的JSP應用系統(tǒng)中,頁頭、頁腳部分往往被抽取出來,然后根據(jù)需要引入頁頭、頁腳。當前,在JSP頁面中引入外部資源的方法主要有兩種:include指令,以及include動作。

include指令:例如%@ include file="copyright.html" %。該指令在編譯時引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合并成一個文件。被引用的外部資源在編譯時就確定,比運行時才確定資源更高效。

include動作:例如jsp:include page="copyright.jsp" /。該動作引入指定頁面執(zhí)行后生成的結(jié)果。由于它在運行時完成,因此對輸出結(jié)果的控制更加靈活。但時,只有當被引用的內(nèi)容頻繁地改變時,或者在對主頁面的請求沒有出現(xiàn)之前,被引用的頁面無法確定時,使用include動作才合算。

24、及時清除不再需要的會話

為了清除不再活動的會話,許多應用服務器都有默認的會話超時時間,一般為30分鐘。當應用服務器需要保存更多會話時,如果內(nèi)存容量不足,操作系統(tǒng)會把部分內(nèi)存數(shù)據(jù)轉(zhuǎn)移到磁盤,應用服務器也可能根據(jù)“最近最頻繁使用”(Most Recently Used)算法把部分不活躍的會話轉(zhuǎn)儲到磁盤,甚至可能拋出“內(nèi)存不足”異常。在大規(guī)模系統(tǒng)中,串行化會話的代價是很昂貴的。當會話不再需要時,應當及時調(diào)用HttpSession.invalidate()方法清除會話。HttpSession.invalidate()方法通??梢栽趹玫耐顺鲰撁嬲{(diào)用。

25、不要將數(shù)組聲明為:public static final 。

26、HashMap的遍歷效率討論

經(jīng)常遇到對HashMap中的key和value值對的遍歷操作,有如下兩種方法:

MapString, String[] paraMap = new HashMapString, String[]();

//第一個循環(huán)

SetString appFieldDefIds = paraMap.keySet();

for (String appFieldDefId : appFieldDefIds) {

String[] values = paraMap.get(appFieldDefId);

......

}

//第二個循環(huán)

for(EntryString, String[] entry : paraMap.entrySet()){

String appFieldDefId = entry.getKey();

String[] values = entry.getValue();

.......

}

第一種實現(xiàn)明顯的效率不如第二種實現(xiàn)。

分析如下 SetString appFieldDefIds = paraMap.keySet(); 是先從HashMap中取得keySet

代碼如下:

public SetK keySet() {

SetK ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private class KeySet extends AbstractSetK {

public IteratorK iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

其實就是返回一個私有類KeySet, 它是從AbstractSet繼承而來,實現(xiàn)了Set接口。

再來看看for/in循環(huán)的語法

for(declaration : expression)

statement

在執(zhí)行階段被翻譯成如下各式

for(IteratorE #i = (expression).iterator(); #i.hashNext();){

declaration = #i.next();

statement

}

因此在第一個for語句for (String appFieldDefId : appFieldDefIds) 中調(diào)用了HashMap.keySet().iterator()

而這個方法調(diào)用了newKeyIterator()

IteratorK newKeyIterator() {

return new KeyIterator();

}

private class KeyIterator extends HashIteratorK {

public K next() {

return nextEntry().getKey();

}

}

所以在for中還是調(diào)用了

在第二個循環(huán)for(EntryString, String[] entry : paraMap.entrySet())中使用的Iterator是如下的一個內(nèi)部

private class EntryIterator extends HashIteratorMap.EntryK,V {

public Map.EntryK,V next() {

return nextEntry();

}

}

此時第一個循環(huán)得到key,第二個循環(huán)得到HashMap的Entry效率就是從循環(huán)里面體現(xiàn)出來的第二個循環(huán)此致可以直接取key和value值而第一個循環(huán)還是得再利用HashMap的get(Object key)來取value值現(xiàn)在看看HashMap的get(Object key)方法

public V get(Object key) {

Object k = maskNull(key);

int hash = hash(k);

int i = indexFor(hash, table.length); //Entry[] table

EntryK,V e = table;

while (true) {

if (e == null)

return null;

if (e.hash == hash eq(k, e.key))

return e.value;

e = e.next;

}

}

其實就是再次利用Hash值取出相應的Entry做比較得到結(jié)果,所以使用第一中循環(huán)相當于兩次進入HashMap的Entry

中而第二個循環(huán)取得Entry的值之后直接取key和value,效率比第一個循環(huán)高。其實按照Map的概念來看也應該是用第二個循環(huán)好一點,它本來就是key和value的值對,將key和value分開操作在這里不是個好選擇。

27、array(數(shù)組) 和 ArryList的使用

array([]):最高效;但是其容量固定且無法動態(tài)改變;

ArrayList:容量可動態(tài)增長;但犧牲效率;

基于效率和類型檢驗,應盡可能使用array,無法確定數(shù)組大小時才使用ArrayList!

ArrayList是Array的復雜版本

ArrayList內(nèi)部封裝了一個Object類型的數(shù)組,從一般的意義來說,它和數(shù)組沒有本質(zhì)的差別,甚至于ArrayList的許多方法,如Index、IndexOf、Contains、Sort等都是在內(nèi)部數(shù)組的基礎上直接調(diào)用Array的對應方法。

ArrayList存入對象時,拋棄類型信息,所有對象屏蔽為Object,編譯時不檢查類型,但是運行時會報錯。

注:jdk5中加入了對泛型的支持,已經(jīng)可以在使用ArrayList時進行類型檢查。

從這一點上看來,ArrayList與數(shù)組的區(qū)別主要就是由于動態(tài)增容的效率問題了

28、盡量使用HashMap 和ArrayList ,除非必要,否則不推薦使用HashTable和Vector ,后者由于使用同步機制,而導致了性能的開銷。

29、StringBuffer 和StringBuilder的區(qū)別:

java.lang.StringBuffer線程安全的可變字符序列。一個類似于 String 的字符串緩沖區(qū),但不能修改。

StringBuilder。與該類相比,通常應該優(yōu)先使用 java.lang.StringBuilder類,因為它支持所有相同的操作,但由于它不執(zhí)行同步,所以速度更快。為了獲得更好的性能,在構(gòu)造 StirngBuffer 或 StirngBuilder 時應盡可能指定它的容量。當然,如果你操作的字符串長度不超過 16 個字符就不用了。 相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%-15% 左右的性能提升,但卻要冒多線程不安全的風險。而在現(xiàn)實的模塊化編程中,負責某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環(huán)境中運行,因此:除非你能確定你的系統(tǒng)的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運行在多線程模式下,否則還是用 StringBuffer 吧。

30、盡量避免使用split

除非是必須的,否則應該避免使用split,split由于支持正則表達式,所以效率比較低,如果是頻繁的幾十,幾百萬的調(diào)用將會耗費大量資源,如果確實需要頻繁的調(diào)用split,可以考慮使用apache的 StringUtils.split(string,char),頻繁split的可以緩存結(jié)果。

其他補充:

1、及時清除不再使用的對象,設為null

2、盡可能使用final,static等關(guān)鍵字

3、盡可能使用buffered對象

如何優(yōu)化代碼使JAVA源文件及編譯后CLASS文件更小

1 盡量使用繼承,繼承的方法越多,你要寫的代碼量也就越少

2 打開JAVA編譯器的優(yōu)化選項: javac -O 這個選項將刪除掉CLASS文件中的行號,并能把

一些private, static,final的小段方法申明為inline方法調(diào)用

3 把公用的代碼提取出來

4 不要初始化很大的數(shù)組,盡管初始化一個數(shù)組在JAVA代碼中只是一行的代碼量,但

編譯后的代碼是一行代碼插入一個數(shù)組的元素,所以如果你有大量的數(shù)據(jù)需要存在數(shù)組

中的話,可以先把這些數(shù)據(jù)放在String中,然后在運行期把字符串解析到數(shù)組中

5 日期類型的對象會占用很大的空間,如果你要存儲大量的日期對象,可以考慮把它存儲為

long型,然后在使用的時候轉(zhuǎn)換為Date類型

6 類名,方法名和變量名盡量使用簡短的名字,可以考慮使用Hashjava, Jobe, Obfuscate and Jshrink等工具自動完成這個工作

7 將static final類型的變量定義到Interface中去

8 算術(shù)運算 能用左移/右移的運算就不要用*和/運算,相同的運算不要運算多次

2. 不要兩次初始化變量

Java通過調(diào)用獨特的類構(gòu)造器默認地初始化變量為一個已知的值。所有的對象被設置成null,integers (byte, short, int, long)被設置成0,float和double設置成0.0,Boolean變量設置成false。這對那些擴展自其它類的類尤其重要,這跟使用一個新的關(guān)鍵詞創(chuàng)建一個對象時所有一連串的構(gòu)造器被自動調(diào)用一樣。

3. 在任何可能的地方讓類為Final

標記為final的類不能被擴展。在《核心Java API》中有大量這個技術(shù)的例子,諸如java.lang.String。將String類標記為final阻止了開發(fā)者創(chuàng)建他們自己實現(xiàn)的長度方法。

更深入點說,如果類是final的,所有類的方法也是final的。Java編譯器可能會內(nèi)聯(lián)所有的方法(這依賴于編譯器的實現(xiàn))。在我的測試里,我已經(jīng)看到性能平均增加了50%。

9. 異常在需要拋出的地方拋出,try catch能整合就整合

try {

some.method1(); // Difficult for javac

} catch( method1Exception e ) { // and the JVM runtime

// Handle exception 1 // to optimize this

} // code

try {

some.method2();

} catch( method2Exception e ) {

// Handle exception 2

}

try {

some.method3();

} catch( method3Exception e ) {

// Handle exception 3

}

已下代碼 更容易被編譯器優(yōu)化

try {

some.method1(); // Easier to optimize

some.method2();

some.method3();

} catch( method1Exception e ) {

// Handle exception 1

} catch( method2Exception e ) {

// Handle exception 2

} catch( method3Exception e ) {

// Handle exception 3

}

10. For循環(huán)的優(yōu)化

Replace…

for( int i = 0; i collection.size(); i++ ) {

...

}

with…

for( int i = 0, n = collection.size(); i n; i++ ) {

...

}

5、 在JAVA + ORACLE 的應用系統(tǒng)開發(fā)中,java中內(nèi)嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負擔。

10、盡量采用lazy loading 的策略,即在需要的時候才開始創(chuàng)建。

例如: String str = “aaa”;

if(i == 1) {

list.add(str);

}

應替換為:

if(i == 1) {

String str = “aaa”;

list.add(str);

}

12、不要在循環(huán)中使用:

Try {

} catch() {

}

應把其放置在最外層

java規(guī)則引擎---Jess

該爾杰斯開發(fā)環(huán)境( JessDE )提供的一套插件為流行的開源的IDE Eclipse的;特別是,這些都是Eclipse的插件版本為3.1或更高版本。請注意,只有JessDE作品的充分“的Eclipse SDK的” -規(guī)模較小的“平臺運行二進制”是不夠的。

要安裝JessDE ,只需退出Eclipse的,解壓縮所有文件Jess71p2/eclipse進入最高級別的Eclipse的安裝目錄。確認目錄命名為“ plugins/gov.sandia.jess_7.1.0 ”存在,在你的Eclipse的安裝目錄,然后重新啟動Eclipse的。 //////

這段翻譯的結(jié)果,不是你的SDK 不是 full "Eclipse SDK"

Jess 7.0p1——Java平臺規(guī)則引擎(一) 2008-07-12 22:21

分類:JESS 字號: 大大 中中 小小 1.入門

1.1.需求

Jess是一個用java語言編寫的程序庫。因此要使用Jess你需要Java虛擬機(JVM)。你可以從 Sun Microsystems上免費得到一個非常適合用于Windows, Linux,Solaris上的JVM。Jess 7是兼容所有版本的Java,從開始的JDK 1.4到現(xiàn)在的最新版本JDK1.5。版本更老的編號為4.x的Jess兼容JDK 1.0, 5.x版本兼容的是JDK1.1,Jess 6工作在JDK1.2及以上版本。

在使用Jess前請先確認JVM是否正確安裝并能正常工作。

使用JessDE集成開發(fā)環(huán)境,你需要Eclipse SDK的3.1版或更新版本,這個可以從獲得。安裝JessDE前請確認Eclipse是已經(jīng)安裝并能正常工作。

Jess類庫為另一種語言擔任譯員,這種語言我在本文檔中稱為Jess語言。Jess語言是一種高度專業(yè)化的Lisp形式語言。

我會認為讀者你是將使用這兩種或其中一種語言的一個程序員。并且所有的讀者都至少有起碼Java基礎。另外你必須有一個Java運行系統(tǒng)和知道如何以一個簡單的方法使用這個系統(tǒng)。你應該知道如何用它來:

· 運行一個Java應用程序

· 處理如CLASSPATH變量的配置問題

· 編譯Java源文件集(可選)

如果你沒有對Java的環(huán)境有基本的熟悉,那么我建議你購買了關(guān)于java的基礎的書籍。對與各種平臺的Java軟件以及豐富的教程和文檔可以免費從上獲得。

對于那些將要使用jess語言編寫程序的讀者,我假定你們已經(jīng)熟悉了一般程序編寫的原理。我會說明整個Jess語言,所以熟悉Lisp是不需要(雖然熟悉是有些用的)。此外,在可能范圍內(nèi),我將努力說明基于規(guī)則系統(tǒng)的最重要的概念,因為它們適用于Jess。再次,我將假定讀者對這些概念有了一定的熟悉程度和了解更多。如果不熟悉基于規(guī)則系統(tǒng),你也許應當考慮購買一本關(guān)于這一主題的書籍。

許多讀者都希望提高Jess的能力,無論是通過向Jess語言加入的命令(用JAVA語言寫)或以Java應用的方式嵌入Jess庫。另外一些人會想用Jess語言的Java集成能力來從Jess語言程序調(diào)用Java函數(shù)。在本文檔專門針對這類讀者的一些章節(jié)中,我將承擔適度Java編程的知識。我不會教Java語言任何方面的知識,有興趣的讀者可到您當?shù)氐臅陞㈤喯嚓P(guān)書籍。

這個文檔包含了一個目錄,在很多書上這些主題也都被列舉出來。

1.2.準備

1.2.1.安裝包的組成

Jess提供一個可用于所有支持平臺的單獨的.zip壓縮包。這個單獨的文件壓縮包包含在Windows,UNIX,或Macintosh系統(tǒng)上使用Jess的所有你需要(除了JVM你必須自己安裝)的資源。當Jess是解壓后,你應該有一個命名為jess71a2 /的目錄。在這個目錄路徑有下列文件和子目錄:

README

快速開始指導.

LICENSE

關(guān)于Jess使用的您的權(quán)利信息.

bin

一個包含Windows 批處理文件(jess.bat)和一個UNIX腳本(Jess)的目錄,你可以使用它們啟動Jess命令提示符.

lib

該目錄含有作為一個Java檔案文件的Jess本身。注意,這不是一個“點擊”存檔文件,你不可以通過雙擊它運行Jess。這是要注意的。在這個目錄的jsr94.jar包中又包含了符合JSR - 94 (javax.rules)的API。

docs/

這是一個文檔,以“index.html”為首頁的Jess手冊。.

examples/jess

一個包含使用Jess語言編寫的小程序的目錄.

examples/xml

一個包含使用JessML, Jess's XML規(guī)則語言編寫的小程序的目錄.

eclipse

JessDE, 是Jess集成開發(fā)環(huán)境, 提供支持Eclipse 3.0的插件集??催@里的安裝說明。

src (Optional)

如果這個目錄存在,它包含全部的Jess規(guī)則引擎和開發(fā)環(huán)境的源代碼,包括一個構(gòu)建它的Ant腳本。

1.2.2.命令行界面

Jess有一個交互的命令行界面。分布包括兩個你能運行Jess命令提示符的腳本:其中一個用于Windows,另一個用于UNIX。它們兩個都在bin/ directory目錄下。運行適合你系統(tǒng)的那一個,然后你應該看到以下的界面:

C:\Jess71a2 bin\jess.bat

Jess, the Rule Engine for the Java Platform

Copyright (C) 2006 Sandia Corporation

Jess Version Jess71a2 9/5/2006

Jess

這就是Jess的命令。嘗試計算一個前綴數(shù)學表達式"(+ 2 2)"。不要忘記那些括號!

Jess (+ 2 2)

4

Jess計算了此函數(shù),并打印結(jié)果。在這份文檔的下一章,我們會發(fā)現(xiàn)Jess規(guī)則語言本身的語法。

通過Jess命令行執(zhí)行Jess代碼編寫的文件,可以使用批處理命令:

Jess (batch "examples/jess/sticks.clp")

Who moves first (Computer: c Human: h)?

在前面的例子應注意到,在Jess提示符后鍵入命令,Jess將在下一行響應命令。我將在整個這本文檔中遵循本約定。

直接從操作系統(tǒng)提示符執(zhí)行這樣的Jess程序,你可以把程序的名字作為Jess腳本的一個參數(shù),這樣就可以啟動:

C:\Jess71a2 bin\jess.bat examples\jess\sticks.clp

Jess, the Rule Engine for the Java Platform

Copyright (C) 2006 Sandia Corporation

Jess Version Jess71a2 8/28/2006

Who moves first (Computer: c Human: h)?

jess.console類是一個簡單的jess命令行界面的圖形版。你在窗口的底部輸入一個命令,結(jié)果就會出現(xiàn)在滾動窗口之上。試著從Jess71a2路徑下鍵入下面命令:

C:\Jess71a2 java -classpath lib\jess.jar jess.Console

1.2.3.Java程序設計語言與Jess

要在你的Java程序中把Jess做為庫使用,文件jess.jar(在lib目錄下)必須是以一個標準的擴展名安裝在類路徑之下,或者對你的開發(fā)工具配置后能夠識別它。做好這些工作的細節(jié)是隨系統(tǒng)和環(huán)境而定的,但在設置一個類路徑時通常涉及修改環(huán)境變量,并且安裝一個標準的擴展名,簡單來說就是復制jess.jar到你的$(JAVA_HOME)/jre/lib/ext路徑下??刹殚咼ava文檔或介紹Java的文本以了解更多的細節(jié)。

1.2.4.Jess例子程序

有一些簡單的例子程序(在examples/jess和examples/xml目錄下),您可以用這些程序測試你的Jess是否已經(jīng)安裝正確。這些程序包括fullmab.clp,zebra.clp和wordgame.clp。fullmab.clp是關(guān)于猴子與香蕉問題的經(jīng)典版本。要從命令行運行它,只需要輸入:

C:\Jess71a2 bin\jess examples\jess\fullmab.clp

和要運行的問題,就會在屏幕上輸出結(jié)果。任何Jess代碼的文件都可以以這種方式運行。像使用批處理函數(shù)一樣在命令行給一個Jess文件名就可以運行了。因此,一般你只需要保證文件是以:

Jess (reset)

(run)

結(jié)束或根本沒有規(guī)則將運行。zebra.clp和wordgame.clp程序是兩個典型的例子,它們是用來展示Jess如何處理復雜情況的程序。這些例子都產(chǎn)生大量的局部模式匹配,因此它們運行非常慢而且使用了大量的內(nèi)存。另外的例子包括sticks.clp (互動游戲)和frame.clp (一個使用jess的java集成能力建立圖形界面的演示)。

XML的例子在單獨的子目錄下,每個子目錄中都包含有運行例子說明的自述文件。

2.Jess開發(fā)環(huán)境

Jess 7包括一個基于Eclipse的開發(fā)環(huán)境。這個開發(fā)環(huán)境有一個編輯器,一個調(diào)試器和一個Rete網(wǎng)絡視圖。在將來發(fā)布的版本中將包含更多組件(規(guī)則瀏覽器和其它工具)。

2.1.安裝JessDE

Jess開發(fā)環(huán)境(JessDE)是作為一個插件集支持流行的開源的集成開發(fā)環(huán)境Eclipse;該插件支持Eclipse 3.1及其更新版本。應該注意的是JessDE僅僅工作在完全的" Eclipse SDK "上——較小的"二進制運行平臺"是不能運行的。

安裝JessDE,首先要退出Eclipse,然后從Jess71a2/eclipse解壓縮所有文件到頂層的Eclipse的安裝路徑。確認在你的eclipse安裝目錄有一個名為" plugins/gov.sandia.jess_7.0.0 "的目錄存在,然后重新啟動Eclipse。

注意!如果你只是從以前的版本的JessDE更新,你必須在Eclipse的命令行使用"-clean "命令開關(guān),強制更新緩存中有關(guān)JessDE插件的信息。如果你不這樣做,很多的JessDE的選項可能被禁用,安裝后你只需要這樣做一次。

2.1.1.驗證你的安裝

在“Help”菜單下選擇“about Eclipse SDK”。在" about Eclipse SDK "主窗口有一個有Jess標志的按鈕。單擊“Plug-in Details”,如果JessDE已安裝妥當,你將發(fā)現(xiàn)三個或四個Jess相關(guān)插件在列表上——在我的Eclipse中,它們出現(xiàn)在底部。

然后使用“New Project”向?qū)Ы⒁粋€Java工程。在新的工程中創(chuàng)建一個新文件并命名為“hello.clp”。這個文件會在一個Jess的編輯器中打開,這個編輯器有一個帶紅色“J”字的銀色小球的圖標。輸入一些Jess代碼,如下:

(printout t "Hello, World" crlf)

你應該看到合適的語法被高亮顯示。如果看到,祝賀你!工作一切正常!閱讀更多JessDE其他功能的信息。

2.1.2.更多的細節(jié)

JessDE編輯器在你的Jess文件中能夠標示出語法錯誤和警告。你很可能希望這些標記能出現(xiàn)在Eclipse的“Problems”視圖中,盡管在默認情況下它們可能沒有顯示出來。安裝完成JessDE后,重新啟動Eclipse,在Problems的視圖,在標題欄點擊“Filters”的圖標,然后選擇標著" Jess Problem "(如果沒有被選中的話)多選項。你的Problems視圖應該馬上就會顯示Jess錯誤和警告。

要使用Rete網(wǎng)絡視圖,你需要安裝Eclipse圖形編輯框架(GEF)。你可以從Eclipse工程項目頁面得到GEF,或通過Eclipse的內(nèi)置式更新管理器安裝它。然后打開這一視圖,在“Jess Debugger”組之下Eclipse的“Show view”對話框找到它。那么在Jess編輯窗口中當光標停在某一內(nèi)部規(guī)則時,Rete網(wǎng)絡視圖將會為這項規(guī)則顯示出編譯的網(wǎng)絡。

2.2.使用JessDE

2.2.1.Jess語言編輯器

JessDE編輯器可以編輯“.clp”格式的文件。在默認情況下你建立的任何 “.clp”格式的文件都將使用JessDE編輯器打開。沒有單獨Jess的視圖,或是Jess項目類型;我們期望大多數(shù)人都將使用JessDE工具來寫Jess/Java混合應用組成的Jess程序,因此JessDE工具將用在Java項目的文件中。在Jess語言代碼中JessDE使用你的Java項目的類路徑以解決Java中類名稱問題——例如,調(diào)用defclass函數(shù)。

編輯器有您期望的一個現(xiàn)代程序編輯器所應具有的全部功能。

可定制的語法變色

你可以使用Eclipse全局參數(shù)對話框中的“Jess Editor”表來改變默認的顏色。

提供模板,槽和函數(shù)名的幫助內(nèi)容

在許多不同地方使用JessDE編輯器你可引用Eclipse的" Content Assist "功能;JessDE將使輸入Jess代碼變得更容易。在輸入時可以使用快捷鍵Alt-' / '彈出選擇列表清單。

自動修復代碼的“Quick fix”助手

這個功能默認使用Ctrl-1快捷鍵,快速匹配能立即知道怎樣定義未定義的deftemplates,并為現(xiàn)有的deftemplates(如果它們在相同的文件里被定義)增加新的槽。

實時錯誤檢測標記和錯誤高亮顯示

當你輸入有錯誤和警告時將被高亮顯示

代碼自動格式化

當你輸入時代碼自動縮進。你可以從"Source"菜單下選擇"Format"命令來格式化一個全部的緩沖區(qū)

使用大綱視圖快速導航

Eclipse大綱視圖列出了所有在緩沖區(qū)中定義的結(jié)構(gòu);你可以點擊其中任何一個就能夠迅速定位到它

圓括號匹配和自動插入

當你輸入一個'('或’”’符號,JessDE就會插入匹配的符號。當你的光標移動到下一個圓括號時,JessDE會顯示與之相匹配的圓括號。

通過懸停獲得Jess函數(shù)和結(jié)構(gòu)在線幫助

快速訪問Jess手冊中每一個函數(shù)和結(jié)構(gòu)類型的描述。

支持deftemplates 和 deffunctions的懸停幫助

如果你將你的滑鼠移動到一個deftemplate或deffunction的名字上,任何代碼處,JessDE都將顯示一個關(guān)于這個模板或函數(shù)信息的"tooltip"。

Jess程序的運行和調(diào)試命令

你可以使用正常Eclipse 的" Run... "菜單或由右擊導航項或在編輯窗口運行或調(diào)試Jess程序。

2.2.2.文件之間的關(guān)聯(lián)

有時候一個*.clp文件依靠其他的*.clp文件中的代碼先被閱讀執(zhí)行。例如,rules.clp 也許需要templates.clp中的定義。沒有這些定義,rules.clp將會出現(xiàn)語法錯誤。為了解決這個問題,你可以使用require*函數(shù)。"require*"讓你清楚的聲明這些關(guān)聯(lián)。

如果一個文件rules.clp依靠在Java中執(zhí)行的Jess命令,你可以僅僅為了這個目標創(chuàng)建一個特殊的文件處理這個問題(你也許稱之為ruledepends.clp),這個特殊的文件包括了編輯器中使rule.clp文件能夠正確解析的所有聲明。如果你添加"(require* ruledepends)"到rules.clp中,僅當這個外部文件存在的話才會解析,因為它有可能正在開發(fā)中。當你部署代碼時,你不需要部署ruledepends.clp,只要rules.clp能夠從Java代碼中取得所需聲明。

"require"機制代替了JessDE的早期版本中的"Source dependencies"屬性表,"Source dependencies"屬性表已不再被支持。

2.2.3.Rete網(wǎng)絡視圖

使用JessDE的"Rete Network View"你可以即時看到一個衍生自任何規(guī)則的Rete網(wǎng)的圖形展示。當這個視圖是打開時(你可以使用Eclipse中的"Windows | View | Other..."對話框打開它),它會顯示基于編輯器插字符所在規(guī)則的Rete網(wǎng)絡,你可以用這個實時看到修改規(guī)則所對應的Rete網(wǎng)絡變化。圖表的布局方式是遠勝于你能從Jess視圖命令中得到的----因為這樣沒有重疊和交叉線,而且每一列的高度都可變。

2.2.4.Jess調(diào)試器

JessDE調(diào)試器可以讓你調(diào)試一個在.clp文件中定義的Jess程序。它具有您期望的圖形調(diào)試器所具有的所有功能:你可以暫停和恢復程序,或以步進方式執(zhí)行。當程序停止時,執(zhí)行堆棧的內(nèi)容將會顯示出來,這樣你就可以檢查在每個堆棧結(jié)構(gòu)中定義的變量。選擇的堆棧結(jié)構(gòu)也可以導航到被執(zhí)行的源碼處。在編輯器窗口的左手邊緣處,你可以通過右鍵單擊某一規(guī)則在任何.clp文件中設置(或清除)斷點。斷點僅能設在函數(shù)(內(nèi)置或用戶自定義)中,所以你不能在defrule 或者deftemplate結(jié)構(gòu)中打斷程序執(zhí)行。然而,你能夠在一個調(diào)用規(guī)則 的左邊或右手邊的函數(shù)中暫停。

3.Jess 語言基礎

大多數(shù)時間你是在使用Jess語言編寫Jess規(guī)則。如果你從來沒有使用過Lisp,第一次使用Jess規(guī)則語言也許看起來就有點奇怪了,但它并不需要太長時間來學習。回報也是豐厚的,你將使用非常少的代碼表達復雜的邏輯關(guān)系。

在這一章,我們將看到Jess語言的基礎語法。在后面的章節(jié)中,我們再來學習怎樣定義像事實與規(guī)則這樣的高級概念,但現(xiàn)在我們將學習最基礎的。

在本語言指導中,我將使用一個非正規(guī)的符號來描述語法。在 中的基本串是必須提供的數(shù)據(jù)類型,在方括號中([])的內(nèi)容是可選的,以 + 結(jié)束表示可以出現(xiàn)一次或多次,以 * 結(jié)束表示可以出現(xiàn)零次或更多。一般來說, Jess的輸入格式是自由的。換行不具有特殊的含義,僅被處理為空格,而異常將被標識。

3.1.符號

符號是Jess語言的一個核心概念。符號是非常類似于其他語言中的標識符。Jess符號包括字母,數(shù)字和下面的標點符號:$*=+/_?#.。一個符號不能以數(shù)字開始,可以以一些特殊的標點符號開始(這些字符作為操作員當出現(xiàn)在符號開始時有著特殊的意義)

Jess符號對于大小寫敏感。foo,F(xiàn)OO,和Foo是不同的符號。

最佳的符號是由字母,數(shù)字,下劃線和破折號組成。破折號是傳統(tǒng)的分隔符。如下所示為合法的符號:

foo first-value contestant#1 _abc

Jess中有三種特殊的符號。零,和java中的空值有點類似;真和假是Jess中的布爾類型的值。

3.2.數(shù)字

Jess分別使用Java函數(shù)parseInt(java.lang.String), parseLong(java.lang.String)和parseDouble(java.lang.String)來解析整型,長整型和浮點型數(shù)字。參考本文檔中關(guān)于這些方法精確的語法描述。如下為合法的數(shù)字:

3 4. 5.643 5654L 6.0E4 1D

3.3.字符串

Jess中的字符串是用雙引呈來標識的(").。反斜線能夠區(qū)分嵌入的引號。注意Jess的字符串和Java的字符串在一些重要的地方是不一樣的。首先,不會認識轉(zhuǎn)義序列。比如說你不能用一個"\n"字符串來換行。另一方面,真正的換行可以通過雙引號中的字符串來實現(xiàn)。他們是字符串的一部分。如下為合法的字符串:

"foo" "Hello, World" "\"Nonsense,\" he said firmly." "Hello,

There"

最后一個字符串相當于Java中的字符串"Hello,\nThere".。

3.4.列表

Jess中的另一個基礎語法元素是列表。列表是由圓括號和空,符號,數(shù)字,字符串和其他列表組成。如下所示為合法的列表:

(+ 3 2) (a b c) ("Hello, World") () (deftemplate foo (slot bar))

Jess中列表的第一個元素(Lisp中稱為列表的car)通常被稱列表的頭。

3.5.注釋

Jess支持兩種類型的程序注釋。Lisp風格的行注釋和C風格的塊注釋。行注釋是以分號開頭,延伸到文本中本行的最后。這里有一個行注釋的例子:

; This is a list

(a b c)

塊注釋就和他們在C語言中的用法一樣:他們以兩個特征符"/*"開始,以"*/"結(jié)束。塊注釋不能嵌套。

/*

Here is an example of a list (commented out):

(a b c)

*/

注釋可以在Jess程序的任何地方出現(xiàn),包括模板和規(guī)則的結(jié)構(gòu)里。

3.6.函數(shù)調(diào)用

和Lisp一樣,Jess中的所有代碼(控制結(jié)構(gòu),分配,程序調(diào)用)都是以函數(shù)調(diào)用的方式進行的。沒有操作器,一切都是函數(shù)調(diào)用。然而,有些函數(shù)的名字使它們看起來像是Java操作器,在這種情況下,它們就和它們的Java 副本工作的非常相似。

Jess中的函數(shù)調(diào)用可以理解為簡單的列表。函數(shù)調(diào)用采用前綴表示,如果一個列表的頭部是一個已經(jīng)存在的函數(shù)的符號,那么它就可以稱為是一個函數(shù)調(diào)用。舉例來說,用+函數(shù)來算2和3相加的表達式應該寫為(+ 2 3)。在計算時,這個表達式的結(jié)果是數(shù)字5(不是一個僅包含數(shù)字5的列表?。Mǔ碚f,在合適的時候表達式都被看作是這樣并通過上下文求值。你可以在Jess提示符后鍵入表達式。Jess計算表達式并打印出結(jié)果:

Jess (+ 2 3)

5

Jess (+ (+ 2 3) (* 3 3))

14

注意你可以嵌套調(diào)用函數(shù);外部函數(shù)是形成內(nèi)部函數(shù)調(diào)用計算的因素。

Jess自身帶有大量的內(nèi)置函數(shù),它們可以用來做一切事情,如數(shù)學計算,程序控制和字符處理,讓你能夠使用Java的API函數(shù)。當然你也可以在Jess語言或者是Java語言中定義自己的函數(shù)。

其中一個最經(jīng)常用的函數(shù)是printout,它是用來發(fā)送文本到Jess的標準輸出窗口,或者是輸出到一個文件中。完善的解釋你必須等待,但是現(xiàn)在,你所要了解的都包含在下面這個例子中:

Jess (printout t "The answer is " 42 "!" crlf)

The answer is 42!

另一個常用的函數(shù)是batch,它是用來計算一個包含Jess代碼文件的。要運行Jess源文件examples/jess/hello.clp,你可以鍵入:

ess (batch "examples/jess/hello.clp")

Hello, world!

Jess自帶的其他的所有函數(shù)的詳細說明都在Jess function guide.。

3.7.變量

Jess中程序變量是以問號開始的標識符。問號也是變量名的一部分。名字可以包括字母,數(shù)字,破折號,下劃線,分號和星號的任何組合。

一個變量可以看作是一個簡單的符號,數(shù)字,字符串或者是一個列表。你可以用bind函數(shù)來為變量指定一個值。

Jess (bind ?x "The value")

"The value"

變量在第一次使用前不需要聲明(全局變量除外)。

想在Jess提示符后看到變量 的值,你只需要鍵入變量的名字:

Jess (bind ?a 123)

123

Jess ?a

123

3.7.1.全局變量(默認全局)

你在Jess提示符后或者任何Jess語言程序頂層創(chuàng)建的所有變量, 當重置命令運行的時候都將被清除。這樣就使它們稍嫌短暫,對于暫時性變量它們很好用,在標準理解的前提下不是永久全局變量。要創(chuàng)建不被reset銷毀的全局變量,你可以用全局結(jié)構(gòu):

(defglobal [?global-name = value]+)

全局變量的名稱必須是以星號開頭以星號結(jié)束。合法的全局變量如下:

?*a* ?*all-values* ?*counter*

當全局變量建立以后,它會被初始化賦值。當reset命令隨后執(zhí)行的時候,這個變量可能會用相同的值重新設置,當然這取決于reset-globals的屬性設置。有一個稱為set-reset-globals的函數(shù)可以用來設置這個屬性。如例所示:

Jess (defglobal ?*x* = 3)

TRUE

Jess ?*x*

3

Jess (bind ?*x* 4)

4

Jess ?*x*

4

Jess (reset)

TRUE

Jess ?*x*

3

Jess (bind ?*x* 4)

4

Jess (set-reset-globals nil)

FALSE

Jess (reset)

TRUE

Jess ?*x*

4

您可以閱讀Jess function guide.中有關(guān)set-reset-globals和相關(guān)的get-reset-globals函數(shù)的信息。

3.8.控制流

Java中控制流(分支和循環(huán),異常處理等)都是由一些特殊的語法和關(guān)鍵字如if,while,for,和try等來引導的。在Jess中,就如我們前面說過的,所有的一切都是函數(shù)調(diào)用,控制流也不例外。因此,Jess包含有那些名為if,while,for,和try以及foreach等函數(shù)。這些函數(shù)就和Java體系中相同名稱的結(jié)構(gòu)工作起來類似。

3.8.1.簡單循環(huán)

例如,如下 是Jess中的一個“while”循環(huán)示例:

Jess (bind ?i 3)

3

Jess (while ( ?i 0)

(printout t ?i crlf)

(-- ?i))

3

2

1

FALSE

While循環(huán)的第一個參數(shù)是一個布爾表達式。While函數(shù)計算它的第一個參數(shù),如果它為真,就計算它所有其他的參數(shù)。它一直進行這個過程直到它的線一個參數(shù)值為假。一個while循環(huán)總是返回FALSE.

Jess中內(nèi)置有一些其他的循環(huán)函數(shù)。詳情參看Jess function index.中關(guān)于for和foreach的有關(guān)描述。Jess中有一個break函數(shù),可以有來跳出循環(huán),也可以很早的從一個規(guī)則的右手邊返回

//原文地址

如何優(yōu)化JAVA代碼及提高執(zhí)行效率

網(wǎng)站優(yōu)化通常包含兩方面的內(nèi)容:減小代碼的體積和提高代碼的運行效率。減小代碼的體積已經(jīng)寫過太多這類的文章了,下面就簡單討論下如何提高代碼的效率。一、不用new關(guān)鍵詞創(chuàng)建類的實例用new關(guān)鍵詞創(chuàng)建類的實例時,構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會被自動調(diào)用。但如果一個對象實現(xiàn)了Cloneable接口,我們可以調(diào)用它的clone()方法。clone()方法不會調(diào)用任何類構(gòu)造函數(shù)。在使用設計模式(DesignPattern)的場合,如果用Factory模式創(chuàng)建對象,則改用clone()方法創(chuàng)建新的對象實例非常簡單。二、使用非阻塞I/O版本較低的JDK不支持非阻塞I/OAPI。為避免I/O阻塞,一些應用采用了創(chuàng)建大量線程的辦法(在較好的情況下,會使用一個緩沖池)。這種技術(shù)可以在許多必須支持并發(fā)I/O流的應用中見到,如Web服務器、報價和拍賣應用等。然而,創(chuàng)建Java線程需要相當可觀的開銷。JDK1.4引入了非阻塞的I/O庫(java.nio)。如果應用要求使用版本較早的JDK,需要支持非阻塞I/O的軟件包。三、慎用異常異常對性能不利。拋出異常首先要創(chuàng)建一個新的對象。Throwable接口的構(gòu)造函數(shù)調(diào)用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調(diào)用跟蹤信息。只要有異常被拋出,VM就必須調(diào)整調(diào)用堆棧,因為在處理過程中創(chuàng)建了一個新的對象。異常只能用于錯誤處理,不應該用來控制程序流程。四、不要重復初始化變量默認情況下,調(diào)用類的構(gòu)造函數(shù)時,Java會把變量初始化成確定的值:所有的對象被設置成null,整數(shù)變量(byte、short、int、long)設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因為用new關(guān)鍵詞創(chuàng)建一個對象時,構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會被自動調(diào)用。五、盡量指定類的final修飾符帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個類為final,則該類所有的方法都是final。Java編譯器會尋找機會內(nèi)聯(lián)(inline)所有的final方法(這和具體的編譯器實現(xiàn)有關(guān))。此舉能夠使性能平均提高50%。六、盡量使用局部變量調(diào)用方法時傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時變量都保存在棧(Stack)中,速度較快。其他變量,如靜態(tài)變量、實例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。另外,依賴于具體的編譯器/JVM,局部變量還可能得到進一步優(yōu)化,望采納,謝謝。


當前文章:JAVA規(guī)則引擎簡化代碼,java代碼設計原則
網(wǎng)站URL:http://weahome.cn/article/hcjsdh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部