1.switch條件語句中可以加入字串了,實作方法是利用了字串的hashcode()值作業真正的值
2.增加了一種可以在字面量中使用的進制,二進制,透過在數字前面加“0b”或“0B”
3.在數字字面量中使用底線來分隔數字方便閱讀,不影響數值大小。基本原則是前後都是數字的才可以出現底線
4.java7對異常做了兩個改動:
4.1.支援在一個catch子句中同時捕獲多個異常,另外一個是在捕獲並重新拋出異常時的異常類型更加精確。 java7中Throwable類別增加addSuppressed方法,當一個異常被拋出的時候,可能有其他異常因為該異常而被抑制住,從而無法正常拋出。這時可以透過addSuppressed方法把這些被抑制的方法記錄下來,被抑制的異常會出現在拋出的異常的堆疊資訊中,也可以透過getSuppressed方法來取得這些異常。這樣做的好處是不會遺失任何異常,方便開發人員測試。
java7改進了catch子句的語法,允許在其中指定多種異常,每個異常類型之間使用「|」來分隔。需要注意的是在catch子句中聲明捕獲的這些異常,不能出現重複的類型,也不允許其中的某個異常是另外一個異常參數的子類,否則會出現編譯錯誤(從小到大寫就沒問題)。如果在catch子句中聲明了多個異常,那麼異常參數的具體類型是所有這些異常類型的最小上界。
4.2使用try(申請資源){業務處理}來自動釋放資源,能夠被try語句所管理的資源需要滿足一個條件,那就是其java類別要實現java.lang.AutoCloseable接口,否則會出現編譯錯誤。當需要釋放資源的時候該介面的close方法會被自動呼叫。
5. 優化變長參數的方法呼叫:
j2se5.0中引入的一個新特性就是允許在方法宣告中使用可變長度的參數。一個方法的最後一個形式參數可以被指定為代表任意多個相同類型的參數。在呼叫的時候,這些參數是以數組的形式來傳遞的。在方法體中也可以按照陣列的方式來引用這些參數。
6. java7引入了一個新的註解@SafeVarargs.如果開發人員確信某個使用了可變長度參數的方法,在與泛型類一起使用進不會出現類似的情況,就可以用這個註解進行聲明。 @SafeVarargs註解只能用在參數長度可變的方法或構造方法上,且方法必須宣告為static或final,否則會出現編譯錯誤。一個方法使用@SafeVarargs註解的前提是,開發人員必須確保這個方法的實作中對泛型類型參數的處理不會引發型別安全問題。
7.java中在java虛擬機器中支援一些腳本語言是透過腳本引擎。實際上腳本引擎管理器共支援三種查找引擎方式,分別透過名稱,檔案副檔名和MIME類型來完成。如
7.1 語言綁定:
腳本語言支援api的一個很大優勢在於它規範了java語言與腳本語言之間的互動方式,使java語言編寫的程式可以與腳本之間進行雙向的方法呼叫和資料傳遞。資料傳遞是透過語言綁定物件來完成的。所謂的語言綁定物件就是一個簡單的哈希表,用來存放和取得需要共享的資料。所有資料都對應這個哈希表中的一個條目,是簡單的名值對。介面javax.script.Bingings定義了語言綁定物件的接口,它繼承自java.util.Map介面。一個腳本引擎在執行過程中可能會使用多個語言綁定物件。不同語言綁定物件的作用域不同。在預設情況下,腳本引擎會提供多個語言綁定對象,用來存放在執行過程中產生的全域對像等。 ScriptEnging類別提供了put和get方法對腳本引擎中特定使用哉的預設語言綁定物件進行操作。程式可以直接使用這個預設的語言綁定對象,也可以使用自己的語言綁定對象。在腳本執行過程中,可以將語言綁定物件看成是一個額外的變數映射表。在解析變數值的時候,語言綁定物件中的名稱也會被考慮。腳本執行過程中產生的全域變數等內容,會出現在語言綁定物件中。透過這種方式,就完成了Java與腳本語言之間的雙向資料傳遞。
如透過ScriptEngine的put方法向腳本引擎預設的語言綁定物件中加入了一個名為「name」的字串,接著在腳本中直接根據名稱來引用這個物件。同樣,在腳本中建立的全域變數「message」也可以透過ScriptEnging的get方法來取得。這樣就實作了Java程式與腳本之間的雙向資料傳遞。資料傳遞過程中的類型轉換是由腳本引擎來完成的,轉換規則取決於具體的語言的語法
在大多數情況下,使用ScriptEnging的put和get方法就足夠了。如果僅使用put和get方法,語言綁定物件本身對於開發人員來說是透明的。在某些情況下,需要使用程式自己的語言綁定對象,例如語言綁定對像中包含了程式自己獨有的資料。如果希望使用自己的語言綁定對象,可以呼叫腳本引擎的creatBingings方法或創建一個javax.script.SimpleBingings對象,並傳遞給腳本引擎的eval方法如:
透過eval方法傳遞的語言綁定對象,僅在當前eval呼叫中生效,並不會改變引擎預設的語言綁定對象
7.2 腳本執行上下文與腳本引擎執行相關的另一個重要介面是javax.script.ScriptContext,其中包含腳本引擎執行過程中的相關上下文信息,可以與JavaEE中servlet規範中的javax.servlet.ServletContext接口來進行類比。腳本引擎透過引上下文物件來獲取與腳本執行相關的信息,也允許開發人員透過此物件來配置腳本引擎的行為。此上下物件中主要包含以下3類資訊。
7.2.1 輸入與輸出首先介紹與腳本輸入和輸出相關的配置訊息,其中包括腳本在執行中用來讀取資料輸入的java.io.Reader物件以及輸出正確內容和出錯訊息的java.io.Writer對象。在預設情況下,腳本的輸入輸出都發生在標準控制台中,如果希望把腳本的輸出寫入到檔案中,可以使用以下程式碼。透過setWriter方法把腳本的輸出重新導向到一個檔案。透過ScriptContext的setReader和setErrorWriter方法可以分別設定腳本執行時的資料輸入來源和產生錯誤時出錯訊息的輸出目的。
7.2.2 自訂屬性
ScriptContext中也有與ServletContext中類似的取得和設定屬性的方法,即setAttribute和getAttribute.所不同的是,ScriptContext中的屬性是有作用域之分的。不同作用域的差異在於查找時的順序不同,每個作用域都以一個對應的整數表示其查找順序。此整數值越小,表示查找時的順序越優先。優先權高的作用域中的屬性會隱藏優先權低中的同名屬性。因此,設定屬性時需要明確指定所在的作用域。在取得屬性的時候,即可選擇指定的作用域中查找,也可以選擇根據作用域優先權自動進行查找。
不過腳本執行上下文實作中包含的作用域是固定的。開發人員不能隨意定義自己的作用域。透過ScriptContext的getScopes方法可以得到所有可用的作用域清單。 SciptContext中預先定義了兩個作用域:常數ScriptContext.ENGINE_SCOPE表示的作用域對應的是當前的腳本引擎,而ScriptContext.GLOBAL_SCOPE表示的作用域對應的是從同一引擎工廠中創建出來的所有腳本引擎物件。前者的優先順序較高。如下例:
7.2.3 語言綁定對象
腳本執行上下文中的最後一類資訊是語言綁定物件。語言綁定物件也是與作用域相對應的。同樣的作用域優先順序對語言綁定物件也適用。這樣的優先順序會對腳本執行時的變數解析產生影響。如下例:
bindings.put("name","World")
engine.eval("println(name);");
7.3 腳本的編譯:
腳本語言一般是解釋執行的。腳本引擎在執行時需要先解析腳本之後再執行。一般來說,透過解釋執行的方式來運行腳本的速度比編譯之後再運行會慢一些。當一段腳本需要被重複執行多次時,可以先對腳本進行編譯。編譯之後的腳本執行時不需要重複解析,可以提高執行效率。不是所有腳本引擎都支援對腳本進行編譯。如果腳本引擎支援這一特性,它會實作javax.script.Compilable介面來聲明這一點。腳本引擎的使用者可以利用這個能力來提高需要多次執行的腳本的運作效率。 Java SE中自帶的JavaScript腳本引擎是支援對腳本進行編譯的。
如下程式碼中,Compilable介面的compile方法用來對腳本程式碼進行編譯,編譯的結果用javax.script.CompiledScript來表示。由於不是所有的腳本引擎都支援Compilable接口,因此這裡需要用instanceof來判斷。在run方法中,透過CompiledScript的eval方法就可以執行腳本。程式碼中把一段腳本重複執行了100次,以此說明編譯完的腳本在重複執行時的效能優勢。
public void run(String scriptText) throws ScriptException {
CompiledScript script = compile(scriptText);
if (script == null) {
return;
}
for (int i = 0; i < 100; i++) {
script.eval();
}
}
7.4 腳本中方法呼叫在腳本中,最常見的、最實用的就是方法。有些腳本引擎允許使用者單獨呼叫腳本中某個方法。支援這種方法呼叫方式的腳本引擎可以實作javax.script.Invocable介面。透過Invocable介面可以呼叫腳本中的頂層方法,也可以呼叫物件中的成員方法。如果腳本中頂層方法或物件中的成員方法實作了Java中的接口,可以透過Invocable接口中的方法來取得腳本中對應的Java接口的實作物件。這樣就可以在Java語言中定義接口,在腳本中實作接口。程式中使用該介面的其他部分程式碼並不知道介面是由腳本來實現的。與Compilable介面一樣,ScriptEngine對於Invocable介面的實作也是可選的。
下面程式碼透過Invocable介面的invokeFunction來呼叫腳本中的頂層方法,呼叫時的參數會被傳遞給腳本中的方法。因為JavaSE自帶的JavaScript腳本引擎實現了Invocable接口,所以這裡省去了對引擎是否實現了Invocalbe接口的判斷在java中調用腳本頂層方法的示例:
//在Java中呼叫腳本物件的成員方法的範例
7.5 腳本中實作java接口
在有些腳本引擎中,可以在Java語言中定義接口,並在腳本中編寫接口的實現,這樣程式中的其他部分可以只同Java接口交互,並不需要關心接口是由什麼方式來實現的。在下面程式碼中Greet是用Java定義的接口,其中包含一個getGreeting方法。在腳本中實作這個接口,透過getInterface方法可以得到由腳本實現的這個接口的對象,並呼叫其中的方法。
由於腳本語言的語法簡單和靈活,非常適用於沒有或只有少量程式設計背景的使用者來使用,這些使用者可以透過腳本語言來定製程式的業務邏輯和使用者介面等,透過腳本語言可以在程式的易用性和靈活性之間達到一個比較好的平衡。例如腳本語言Lua就被廣泛應用在遊戲開發中,用來對遊戲的內部行為和使用者介面進行客製化。
8. 反射API在為Java程式帶來靈活性的同時,也產生了額外的效能代價,由於反射API的實作機制,對於相同的操作,例如呼叫一個方法,用反射API來動態實作比直接在來源程式碼中寫的方式大概慢一到兩個數量級。隨著Java虛擬機器實現的改進,反射API的效能已經有了非常大的提升。但是這種效能的差距是客觀存在的,因此,在某些對效能要求比較高的應用中,要慎用反射API。