1. 程式人生 > >jdk 1.5 1.6 1.7 1.8 1.9的新特性詳解帶例子

jdk 1.5 1.6 1.7 1.8 1.9的新特性詳解帶例子

1.5
1.自動裝箱與拆箱:
2.列舉(常用來設計單例模式)
3.靜態匯入
4.可變引數
5.內省



1.6
1.Web服務元資料
2.指令碼語言支援
3.JTable的排序和過濾
4.更簡單,更強大的JAX-WS
5.輕量級Http Server
6.嵌入式資料庫 Derby



1.7
1,switch中可以使用字串了
2.運用List tempList = new ArrayList<>(); 即泛型例項化型別自動推斷
3.語法上支援集合,而不一定是陣列
4.新增一些取環境資訊的工具方法
5.Boolean型別反轉,空指標安全,參與位運算
6.兩個char間的equals
7.安全的加減乘除
8.map集合支援併發請求,且可以寫成 Map map = {name:"xxx",age:18};



1.8
1. 允許在介面中有預設方法實現
2. Lambda表示式
3. 函式式介面
4. 方法和建構函式引用
5. Lambda的範圍
6. 內建函式式介面
7. Streams
8. Parallel Streams
9. Map
10. 時間日期API
11. Annotations



1.9
1. Jigsaw 專案;模組化原始碼
2. 簡化程序API
3. 輕量級 JSON API
4. 錢和貨幣的API
5. 改善鎖爭用機制
6. 程式碼分段快取
7. 智慧Java編譯, 第二階段
8. HTTP 2.0客戶端
9. Kulla計劃: Java的REPL實現
 

---------------------------------------------------------------------------
JDK1.5新特性:
1自動裝箱與拆箱
Integer iObj = 3;
System.out.println(iObj + 12);
   Integer i1 = 137(-128--127範圍時,為true);
   Integer i2 = 137(-128--127範圍時,為true);
   System.out.println(i1 == i2); //false,但是括號中時卻返回ture,原因是Integer採用的是享元模式

   Integer i3 = Integer.valueOf(213);
   Integer i4 = Integer.valueOf(213);
   System.out.println(i3==i4);//同上,另一種包裝形式

列舉
public class EnumTest {


public static void main(String[] args) {
   WeekDay1 weekDay = WeekDay1.MON;
   System.out.println(weekDay.nextDay());
   WeekDay weekDay2 = WeekDay.FRI;
   System.out.println(weekDay2);
   System.out.println(weekDay2.name());
   System.out.println(weekDay2.ordinal()); 
   System.out.println(WeekDay.valueOf("SUN").toString());
   System.out.println(WeekDay.values().length);
   new Date(300){};
}
public enum WeekDay{
   SUN(1),MON(),TUE,WED,THI,FRI,SAT;
   private WeekDay(){System.out.println("first");}
   private WeekDay(int day){System.out.println("second");}
}


public enum TrafficLamp{
   RED(30){
    public TrafficLamp nextLamp(){
     return GREEN;
    }
   },
   GREEN(45){
    public TrafficLamp nextLamp(){
     return YELLOW;
    }   
   },
   YELLOW(5){
    public TrafficLamp nextLamp(){
     return RED;
    }   
   };
   public abstract TrafficLamp nextLamp();
   private int time;
   private TrafficLamp(int time){this.time = time;}
}
}
3 靜態匯入
import static java.lang.Math.*;
public class StaticImport {
public static void main(String[] args){
   int x = 1;
   try {
    x++;
   } finally {
    System.out.println("template");
   }
   System.out.println(x);


   System.out.println(max(3, 6));
   System.out.println(abs(3 - 6));

}
}
可變引數
public class VarableParameter {


public static void main(String[] args) {


   System.out.println(add(2,3));
   System.out.println(add(2,3,5));  
}




public static int add(int x,int... args){
   int sum = x;



   for(int arg : args){
    sum += arg;
   }
   return sum;
}
}
內省
ReflectPoint pt1 = new ReflectPoint(3,5);
BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
   PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
   Object retVal = null;
   for(PropertyDescriptor pd : pds){
     Method methodGetX = pd.getReadMethod();
     retVal = methodGetX.invoke(pt1);


   }
--------------------------------------
jdk1.6新特性:
1.Web服務元資料
Java 裡的Web服務元資料跟微軟的方案基本沒有語義上的區別,自從JDK5添加了元資料功能(Annotation)之後,SUN幾乎重構了整個J2EE體 系, 由於變化很大,乾脆將名字也重構為Java EE, Java EE(當前版本為5.0)將元資料納入很多規範當中,這其中就包括Web Services的相關規範, 加入元資料之後的Web Services伺服器端程式設計模型就跟上面看到的C#片斷差不多了, 這顯然比以前的JAX-RPC程式設計模型簡單(當然, Axis的程式設計模型也很簡單).這裡要談的Web服務元資料(JSR 181)只是Java Web 服務規範中的一個,它跟Common Annotations, JAXB2, StAX, SAAJ和JAX-WS等共同構成Java EE 5的Web Services技術堆疊.
package WebServices;
import java.io.File;
import java.io.IOException;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;


@WebService(targetNamespace="http://blog.csdn.net/chinajash",serviceName="HelloService")
public class WSProvider {
     @WebResult(name="Greetings")//自定義該方法返回值在WSDL中相關的描述    
     @WebMethod
     public String sayHi(@WebParam(name="MyName") String name){
         return "Hi,"+name; //@WebParam是自定義引數name在WSDL中相關的描述
     }    
     @Oneway //表明該服務方法是單向的,既沒有返回值,也不應該宣告檢查異常
     @WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關的描述
     public void printTime(){
         System.out.println(System.currentTimeMillis());
     }
     public static void main(String[] args) {
         Thread wsPublisher = new Thread(new WSPublisher());
         wsPublisher.start();
     }    
     private static class WSPublisher implements Runnable{
         public void run() {
             //釋出WSProvider到http://localhost:8888/chinajash/WSProvider這個地址,之前必須呼叫wsgen命令
             //生成服務類WSProvider的支援類,命令如下:
             //wsgen -cp . WebServices.WSProvider
             Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
         }        
     }
}


如果想看到Web Services Engine生成的WSDL檔案是否遵守上面的元資料, 我們沒有必要將上面的WSProvider部署到支援JSR-181的應用伺服器或Servlet形式的Web Services Engine,現在JDK6已經提供了一個很簡單的機制可以用來測試和釋出Web Services,下面講講如何在JDK6環境下發布Web Services和檢視生成的WSDL
1.將/bin加入path環境變數
2.在命令列下切換當前目錄到WSProvider的class檔案所在的目錄,執行下面命令
wsgen -cp . WebServices.WSProvider
在這個例子中會生成以下3個類的原始碼檔案及class檔案
SayHi
SayHiResponse
PrintTime
3.執行如下程式碼釋出WSProvider到http://localhost:8888/chinajash/WSProvider,在這裡可以執行WSProvider類的main方法就可以
Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
4.在瀏覽器輸入http://localhost:8888/chinajash/WSProvider?wsdl就可以看到生成的WSDL檔案,為了節省篇幅,這裡就不把生成的WSDL檔案貼上了,大家可以自己動手試試.
2.指令碼語言支援
JDK6增加了對指令碼語言的支援(JSR 223), 原理上是將指令碼語言編譯成bytecode,這樣指令碼語言也能享用Java平臺的諸多優勢,包括可移植性,安全等,另外,由於現在是編譯成 bytecode後再執行,所以比原來邊解釋邊執行效率要高很多。加入對指令碼語言的支援後,對Java語言也提供了以下好處。
1、許多指令碼語言都有動態特性,比如,你不需要用一個變數之前先宣告它,你可以用一個變數存放完全不同型別的物件,你不需要做強制型別轉換,因為轉換都是自動的。現在Java語言也可以通過對指令碼語言的支援間接獲得這種靈活性。
2、 可以用指令碼語言快速開發產品原型,因為現在可以Edit-Run,而無需Edit-Compile-Run,當然,因為Java有非常好的IDE支援,我 們完全可以在IDE裡面編輯原始檔,然後點選執行(隱含編譯),以此達到快速開發原型的目的,所以這點好處基本上可以忽略。
3、通過引入指令碼語言可以輕鬆實現Java應用程式的擴充套件和自定義,我們可以把原來分佈在在Java應用程式中的配置邏輯,數學表示式和業務規則提取出來,轉用JavaScript來處理。


Sun的JDK6實現包含了一個基於Mozilla Rhino的 指令碼語言引擎,支援JavaScript,這並不是說明JDK6只支援JavaScript,任何第三方都可以自己實現一個JSR-223相容的指令碼引擎 使得JDK6支援別的指令碼語言,比如,你想讓JDK6支援Ruby,那你可以自己按照JSR 223 的規範實現一個Ruby的指令碼引擎類,具體一點,你需要實現javax.script.ScriptEngine(簡單起見,可以繼承 javax.script.AbstractScriptEngine)和javax.script.ScriptEngineFactory兩個介面。 當然,在你實現自己的指令碼語言引擎之前,先到scripting.dev.java.net project 這裡看看是不是有人已經幫你做了工作,這樣你就可以直接拿來用就行。


Scripting API
Scripting API是用於在Java裡面編寫指令碼語言程式的API, 在Javax.script中可以找到Scripting API,我們就是用這個API來編寫JavaScript程式,這個包裡面有一個ScriptEngineManager類,它是使用Scripting API的入口,ScriptEngineManager可以通過jar服務發現(service discovery)機制尋找合適的指令碼引擎類(ScriptEngine),使用Scripting API的最簡單方式只需下面三步
1、建立一個ScriptEngineManager物件
2、通過ScriptEngineManager獲得ScriptEngine物件
3、用ScriptEngine的eval方法執行指令碼


下面是一個Hello World程式


public class HelloScript {public static void main(String[] args) throws Exception {         ScriptEngineManager factory = new ScriptEngineManager();//step 1         ScriptEngine engine = factory.getEngineByName("JavaScript");//Step 2             engine.eval_r("print('Hello, Scripting')");//Step 3     }     }執行上面程式,控制檯會輸出Hello, Scripting上面這個簡單的Scripting程式演示瞭如何在Java裡面執行指令碼語言,除此之外,我們還可以利用Scripting API實現以下功能1、暴露Java物件為指令碼語言的全域性變數2、在Java中呼叫指令碼語言的方法3、指令碼語言可以實現Java的介面4、指令碼語言可以像Java一樣使用JDK平臺下的類下面的類演示了以上4種功能
package Scripting;import java.io.File;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptingAPITester {    
 public static void main(String[] args) throws Exception {         ScriptEngineManager manager = new ScriptEngineManager();         ScriptEngine engine = manager.getEngineByName("JavaScript");         testScriptVariables(engine);//演示如何暴露Java物件為指令碼語言的全域性變數          testInvokeScriptMethod(engine);//演示如何在Java中呼叫指令碼語言的方法          testScriptInterface(engine);//演示指令碼語言如何實現Java的介面          testUsingJDKClasses(engine);//演示指令碼語言如何使用JDK平臺下的類     }         public static void testScriptVariables(ScriptEngine engine) throws ScriptException{         File file = new File("test.txt");         engine.put("f", file);         engine.eval_r("println('Total Space:'+f.getTotalSpace())");             }         public static void testInvokeScriptMethod(ScriptEngine engine) throws Exception{         String script = "function hello(name) { return 'Hello,' + name;}";         engine.eval_r(script);         Invocable inv = (Invocable) engine;         String res = (String)inv.invokeFunction("hello", "Scripting" );         System.out.println("res:"+res);     }         public static void testScriptInterface(ScriptEngine engine) throws ScriptException{         String script = "var obj = new Object(); obj.run = function() { println('run method called'); }";         engine.eval_r(script);         Object obj = engine.get("obj");         Invocable inv = (Invocable) engine;         Runnable r = inv.getInterface(obj,Runnable.class);         Thread th = new Thread(r);         th.start();     }         public static void testUsingJDKClasses(ScriptEngine engine) throws Exception{         //Packages是指令碼語言裡的一個全域性變數,專用於訪問JDK的package         String js = "function doSwing(t){var f=new Packages.javax.swing.JFrame(t);f.setSize(400,300);f.setVisible(true);}";         engine.eval_r(js);         Invocable inv = (Invocable) engine;         inv.invokeFunction("doSwing", "Scripting Swing" );     }}Scripting Tool


--------------------------------------------------------------------------------
SUN 提供的JDK6中有一個命令列工具??jrunscript,你可以在/bin下面找到這個工 具,jrunscript是一個指令碼語言的解釋程式,它獨立於指令碼語言,但預設是用JavaScript,我們可以用jrunscript來測試自己寫的 指令碼語言是否正確,下面是一個在命令列執行jrunscript的簡單例子
jrunscript
js>println("Hello,JrunScript");
Hello,JrunScript
js>9*8
72.0
js>
3.JTable的排序和過濾
原來的JTable基本上是隻能顯示資料,在JDK6新增了對JTable的排序和過濾功能,下面程式碼演示了這兩個功能




public class JTableTester {
     static String data[][] = {
         {"China","Beijing","Chinese"},
         {"America","Washington","English"},
         {"Korea","Seoul","Korean"},
         {"Japan","Tokyo","Japanese"},
         {"France","Paris","French"},
         {"England","London","English"},
         {"Germany","Berlin","German"},
     };
     static String titles[] = {"Country","Capital","Language"};
     public static void main(String[] args) {        
         DefaultTableModel m = new DefaultTableModel(data,titles);
         JTable t = new JTable(m);
         final TableRowSorter sorter = new TableRowSorter(m); 
         t.setRowSorter(sorter); //為JTable設定排序器

         JScrollPane sPane = new JScrollPane();
         sPane.setViewportView(t);

         JPanel p = new JPanel();
         p.setLayout(new BoxLayout(p,BoxLayout.X_AXIS));
         JLabel l = new JLabel("Criteria:");
         final JTextField tf = new JTextField();
         JButton b = new JButton("Do Filter");
         p.add(l);
         p.add(tf);
         p.add(b);
         b.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                 if(tf.getText().length()==0){
                     sorter.setRowFilter(null);
                 }else{
                     sorter.setRowFilter(RowFilter.regexFilter(tf.getText()));//為JTable設定基於正則表示式的過濾條件
                 }
             }
         });

         JFrame f = new JFrame("JTable Sorting and Filtering");
         f.getContentPane().add(sPane,BorderLayout.CENTER);        
         f.getContentPane().add(p,BorderLayout.SOUTH);
         f.setSize(400,300);
         f.setVisible(true);
     }

執行上面程式,單擊JTable的某一個title,這個title對應的列就會按照升序/降序重新排列;在下面的Criteria文字框中輸入"ese",點選"Do Filter"按鈕,JTable將只顯示帶有"ese"字串的行,也就是China和Japan兩行,如果文字框裡面什麼都沒有,點選"Do Filter"按鈕,這時JTable會顯示所有的行。
4.更簡單,更強大的JAX-WS
JAX-WS2.0的來歷


--------------------------------------------------------------------------------
JAX-WS(JSR-224) 是Java Architecture for XML Web Services的縮寫,簡單說就是一種用Java和XML開發Web Services應用程式的框架, 目前版本是2.0, 它是JAX-RPC 1.1的後續版本, J2EE 1.4帶的就是JAX-RPC1.1, 而Java EE 5裡面包括了JAX-WS 2.0,但為了向後相容,仍然支援JAX-RPC. 現在,SUN又把JAX-WS直接放到了Java SE 6裡面,由於JAX-WS會用到Common Annotation(JSR 250),Java Web Services Metadata(JSR 181), JAXB2(JSR 222), StAX(JSR 173), 所以SUN也必須把後幾個原屬於Java EE範疇的Components下放到Java SE, 現在我們可以清楚地理解了為什麼Sun要把這些看似跟Java SE沒有關係的Components放進來,終極目的就是要在Java SE裡面支援Web Services.


JAX-WS2.0的架構


--------------------------------------------------------------------------------
JAX-WS不是一個孤立的框架,它依賴於眾多其他的規範,本質上它由以下幾部分組成
1.用來開發Web Services的Java API
2.用來處理Marshal/Unmarshal的XML Binding機制,JAX-WS2.0用JAXB2來處理Java Object與XML之間的對映,Marshalling就是把Java Object對映到XML,Unmarshalling則是把XML對映到Java Object.之所以要做Java Object與XML的對映,是因為最終作為方法引數和返回值的Java Object要通過網路傳輸協議(一般是SOAP)傳送,這就要求必須對Java Object做類似序列化和反序列化的工作,在SOAP中就是要用XML來表示Java object的內部狀態
3.眾多元資料(Annotations)會被JAX-WS用來描述Web Services的相關類,包括Common Annotations, Web Services Metadata, JAXB2的元資料和JAX-WS2.0規範自己的元資料.
4.Annotation Processing Tool(APT) 是JAX-WS重要的組成部分,由於JAX-WS2.0規範用到很多元資料,所以需要APT來處理眾多的Annotations. 在/bin下有兩個命令wsgen和wsimport,就是用到APT和Compiler API來處理碰到的Annotations,wsgen可以為Web Services Provider產生並編譯必要的幫助類和相關支援檔案,wsimport以WSDL作為輸入為Web Service Consumer產生並編譯必要的幫助類和相關支援檔案.
5.JAX-WS還包括JAX-WS Runtime與應用伺服器和工具之間的契約關係


JAX-WS2.0的程式設計模型


--------------------------------------------------------------------------------
現在用JAX-WS2.0來編寫Web Services非常簡單,不像JAX-RPC,JAX-WS可以把任意POJO暴露為Web Services,服務類不需要實現介面,服務方法也沒有必要丟擲RMI異常.下面介紹在JDK6環境下用JAX-WS2.0開發和測試Web Services的步驟
1.編寫服務類,並用Web Services Metadata(JSR-181)標註這個服務類,我用我的另一篇BlogJDK6的新特性之十:Web服務元資料中的WSProvider類作為服務類的例子,在此我重複貼一下WSProvider類的原始碼:


@WebService(targetNamespace="http://blog.csdn.net/chinajash",serviceName="HelloService")
public class WSProvider {
     @WebResult(name="Greetings")//自定義該方法返回值在WSDL中相關的描述    
     @WebMethod
     public String sayHi(@WebParam(name="MyName") String name){
         return "Hi,"+name; //@WebParam是自定義引數name在WSDL中相關的描述
     }    
     @Oneway //表明該服務方法是單向的,既沒有返回值,也不應該宣告檢查異常
     @WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關的描述
     public void printTime(){
         System.out.println(System.currentTimeMillis());
     }
     public static void main(String[] args) {
         Thread wsPublisher = new Thread(new WSPublisher());
         wsPublisher.start();
     }    
     private static class WSPublisher implements Runnable{
         public void run() {
             //釋出WSProvider到http://localhost:8888/chinajash/WSProvider這個地址,之前必須呼叫wsgen命令
             //生成服務類WSProvider的支援類,命令如下:
             //wsgen -cp . WebServices.WSProvider
             Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
         }        
     }
}
2.用wsgen生成上面服務類的必要的幫助類,然後呼叫用EndPoint類的靜態方法publish釋出服務類(步驟請參考我的另一篇Blog JDK6的新特性之十:Web服務元資料),我在這裡是將服務類釋出到http://localhost:8888/chinajash/WSProvider
3.用wsimport為服務消費者(也就是服務的客戶端)生成必要的幫助類,命令如下:
wsimport http://localhost:8888/chinajash/WSProvider?wsdl
這會在<當前目錄>\net\csdn\blog\chinajash下生成客戶端的幫助類,在這個例子中會生成7個類
HelloService.class
ObjectFactory.class
package-info.class
PrintSystemTime.class
SayHi.class
SayHiResponse.class
WSProvider.class
4.在客戶端用下面程式碼即可呼叫步驟1定義的Web Service
HelloService hs = new HelloService();
WSProvider ws = hs.getWSProviderPort();
System.out.println(ws.sayHi("chinajash"));
ws.printSystemTime();
呼叫上述程式碼後客戶端控制檯輸出
hi,chinajash
服務端控制檯輸出伺服器當前系統時間
5.輕量級Http Server
JDK6的新特性之五:輕量級Http Server


JDK6提供了一個簡單的Http Server API,據此我們可以構建自己的嵌入式Http Server,它支援Http和Https協議,提供了HTTP1.1的部分實現,沒有被實現的那部分可以通過擴充套件已有的Http Server API 來實現,程式設計師必須自己實現HttpHandler介面,HttpServer會呼叫HttpHandler實現類的回撥方法來處理客戶端請求,在這裡, 我們把一個Http請求和它的響應稱為一個交換,包裝成HttpExchange類,HttpServer負責將HttpExchange傳給 HttpHandler實現類的回撥方法.下面程式碼演示了怎樣建立自己的H