JDK doc -https://docs.oracle.com/javase/8/docs/technotes/tools/unix/toc.html
1.5
1.自動(dòng)裝箱與拆箱:
2.枚舉(常用來設(shè)計(jì)單例模式)
3.靜態(tài)導(dǎo)入
4.可變參數(shù)
5.內(nèi)省
1.6
1.Web服務(wù)元數(shù)據(jù)
2.腳本語(yǔ)言支持
3.JTable的排序和過濾
4.更簡(jiǎn)單,更強(qiáng)大的JAX-WS
5.輕量級(jí)Http Server
6.嵌入式數(shù)據(jù)庫(kù)Derby
1.7
1缠捌,switch中可以使用字串了
2.運(yùn)用List tempList = new ArrayList<>(); 即泛型實(shí)例化類型自動(dòng)推斷
3.語(yǔ)法上支持集合,而不一定是數(shù)組
4.新增一些取環(huán)境信息的工具方法
5.Boolean類型反轉(zhuǎn),空指針安全,參與位運(yùn)算
6.兩個(gè)char間的equals
7.安全的加減乘除
8.map集合支持并發(fā)請(qǐng)求茵汰,且可以寫成 Map map = {name:"xxx",age:18};
1.8
1. 允許在接口中有默認(rèn)方法實(shí)現(xiàn)
2. Lambda表達(dá)式
3. 函數(shù)式接口
4. 方法和構(gòu)造函數(shù)引用
5. Lambda的范圍
6. 內(nèi)置函數(shù)式接口
7. Streams
8. Parallel Streams
9. Map
10. 時(shí)間日期API
11. Annotations
1.9
1. Jigsaw 項(xiàng)目;模塊化源碼
2. 簡(jiǎn)化進(jìn)程API
3. 輕量級(jí) JSON API
4. 錢和貨幣的API
5. 改善鎖爭(zhēng)用機(jī)制
6. 代碼分段緩存
8. HTTP 2.0客戶端
9. Kulla計(jì)劃: Java的REPL實(shí)現(xiàn)
Java9的14個(gè)新特性總結(jié)- http://geek.csdn.NET/news/detail/196632
---------------------------------------------------------------------------
JDK1.5新特性:
1.自動(dòng)裝箱與拆箱:
Integer?iObj?=?3;
System.out.println(iObj?+?12);
Integer?i1?=?137(-128--127范圍時(shí)氯夷,為true);
Integer?i2?=?137(-128--127范圍時(shí)缕减,為true);
System.out.println(i1?==?i2);?//false厨内,但是括號(hào)中時(shí)卻返回ture位迂,原因是Integer采用的是享元模式
Integer?i3?=?Integer.valueOf(213);
Integer?i4?=?Integer.valueOf(213);
System.out.println(i3==i4);//同上,另一種包裝形式
2.枚舉(常用來設(shè)計(jì)單例模式)
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.靜態(tài)導(dǎo)入
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));
}
}
4.可變參數(shù)
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;
}
}
5.內(nèi)省
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服務(wù)元數(shù)據(jù)
Java?里的Web服務(wù)元數(shù)據(jù)跟微軟的方案基本沒有語(yǔ)義上的區(qū)別,自從JDK5添加了元數(shù)據(jù)功能(Annotation)之后,SUN幾乎重構(gòu)了整個(gè)J2EE體?系,?由于變化很大,干脆將名字也重構(gòu)為Java?EE,?Java?EE(當(dāng)前版本為5.0)將元數(shù)據(jù)納入很多規(guī)范當(dāng)中,這其中就包括Web?Services的相關(guān)規(guī)范,?加入元數(shù)據(jù)之后的Web?Services服務(wù)器端編程模型就跟上面看到的C#片斷差不多了,?這顯然比以前的JAX-RPC編程模型簡(jiǎn)單(當(dāng)然,?Axis的編程模型也很簡(jiǎn)單).這里要談的Web服務(wù)元數(shù)據(jù)(JSR?181)只是Java?Web?服務(wù)規(guī)范中的一個(gè),它跟Common?Annotations,?JAXB2,?StAX,?SAAJ和JAX-WS等共同構(gòu)成Java?EE?5的Web?Services技術(shù)堆棧.
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中相關(guān)的描述
@WebMethod
public?String?sayHi(@WebParam(name="MyName")?String?name){
return?"Hi,"+name;?//@WebParam是自定義參數(shù)name在WSDL中相關(guān)的描述
}
@Oneway?//表明該服務(wù)方法是單向的,既沒有返回值,也不應(yīng)該聲明檢查異常
@WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關(guān)的描述
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()?{
//發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider這個(gè)地址,之前必須調(diào)用wsgen命令
//生成服務(wù)類WSProvider的支持類,命令如下:
//wsgen?-cp?.?WebServices.WSProvider
Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new?WSProvider());
}
}
}
如果想看到Web?Services?Engine生成的WSDL文件是否遵守上面的元數(shù)據(jù),?我們沒有必要將上面的WSProvider部署到支持JSR-181的應(yīng)用服務(wù)器或Servlet形式的Web?Services?Engine,現(xiàn)在JDK6已經(jīng)提供了一個(gè)很簡(jiǎn)單的機(jī)制可以用來測(cè)試和發(fā)布Web?Services,下面講講如何在JDK6環(huán)境下發(fā)布Web?Services和查看生成的WSDL
1.將/bin加入path環(huán)境變量
2.在命令行下切換當(dāng)前目錄到WSProvider的class文件所在的目錄,運(yùn)行下面命令
wsgen?-cp?.?WebServices.WSProvider
在這個(gè)例子中會(huì)生成以下3個(gè)類的源代碼文件及class文件
SayHi
SayHiResponse
PrintTime
3.執(zhí)行如下代碼發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider,在這里可以執(zhí)行WSProvider類的main方法就可以
Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new?WSProvider());
4.在瀏覽器輸入http://localhost:8888/chinajash/WSProvider?wsdl就可以看到生成的WSDL文件九秀,為了節(jié)省篇幅,這里就不把生成的WSDL文件貼上了遗嗽,大家可以自己動(dòng)手試試.
2.腳本語(yǔ)言支持
JDK6增加了對(duì)腳本語(yǔ)言的支持(JSR?223), 原理上是將腳本語(yǔ)言編譯成bytecode鼓蜒,這樣腳本語(yǔ)言也能享用Java平臺(tái)的諸多優(yōu)勢(shì)痹换,包括可移植性征字,安全等,另外娇豫,由于現(xiàn)在是編譯成 bytecode后再執(zhí)行匙姜,所以比原來邊解釋邊執(zhí)行效率要高很多。加入對(duì)腳本語(yǔ)言的支持后冯痢,對(duì)Java語(yǔ)言也提供了以下好處氮昧。
1、許多腳本語(yǔ)言都有動(dòng)態(tài)特性系羞,比如郭计,你不需要用一個(gè)變量之前先聲明它,你可以用一個(gè)變量存放完全不同類型的對(duì)象椒振,你不需要做強(qiáng)制類型轉(zhuǎn)換昭伸,因?yàn)檗D(zhuǎn)換都是自動(dòng)的。現(xiàn)在Java語(yǔ)言也可以通過對(duì)腳本語(yǔ)言的支持間接獲得這種靈活性澎迎。
2庐杨、?可以用腳本語(yǔ)言快速開發(fā)產(chǎn)品原型,因?yàn)楝F(xiàn)在可以Edit-Run夹供,而無(wú)需Edit-Compile-Run灵份,當(dāng)然,因?yàn)镴ava有非常好的IDE支持哮洽,我?們完全可以在IDE里面編輯源文件填渠,然后點(diǎn)擊運(yùn)行(隱含編譯),以此達(dá)到快速開發(fā)原型的目的鸟辅,所以這點(diǎn)好處基本上可以忽略氛什。
3、通過引入腳本語(yǔ)言可以輕松實(shí)現(xiàn)Java應(yīng)用程序的擴(kuò)展和自定義匪凉,我們可以把原來分布在在Java應(yīng)用程序中的配置邏輯枪眉,數(shù)學(xué)表達(dá)式和業(yè)務(wù)規(guī)則提取出來,轉(zhuǎn)用JavaScript來處理再层。
Sun的JDK6實(shí)現(xiàn)包含了一個(gè)基于Mozilla?Rhino的?腳本語(yǔ)言引擎贸铜,支持javascript,這并不是說明JDK6只支持JavaScript聂受,任何第三方都可以自己實(shí)現(xiàn)一個(gè)JSR-223兼容的腳本引擎?使得JDK6支持別的腳本語(yǔ)言蒿秦,比如,你想讓JDK6支持Ruby蛋济,那你可以自己按照J(rèn)SR?223 的規(guī)范實(shí)現(xiàn)一個(gè)Ruby的腳本引擎類渤早,具體一點(diǎn),你需要實(shí)現(xiàn)javax.script.ScriptEngine(簡(jiǎn)單起見瘫俊,可以繼承 javax.script.AbstractScriptEngine)和javax.script.ScriptEngineFactory兩個(gè)接口鹊杖。 當(dāng)然,在你實(shí)現(xiàn)自己的腳本語(yǔ)言引擎之前扛芽,先到scripting.dev.java.Netproject?這里看看是不是有人已經(jīng)幫你做了工作骂蓖,這樣你就可以直接拿來用就行。
Scripting?API
--------------------------------------------------------------------------------
Scripting?API是用于在Java里面編寫腳本語(yǔ)言程序的API川尖,?在Javax.script中可以找到Scripting?API登下,我們就是用這個(gè)API來編寫JavaScript程序,這個(gè)包里面有一個(gè)ScriptEngineManager類叮喳,它是使用Scripting?API的入口被芳,ScriptEngineManager可以通過jar服務(wù)發(fā)現(xiàn)(service?discovery)機(jī)制尋找合適的腳本引擎類(ScriptEngine),使用Scripting?API的最簡(jiǎn)單方式只需下面三步
1馍悟、創(chuàng)建一個(gè)ScriptEngineManager對(duì)象
2畔濒、通過ScriptEngineManager獲得ScriptEngine對(duì)象
3、用ScriptEngine的eval方法執(zhí)行腳本
下面是一個(gè)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?????}?????}運(yùn)行上面程序锣咒,控制臺(tái)會(huì)輸出Hello,?Scripting上面這個(gè)簡(jiǎn)單的Scripting程序演示了如何在Java里面運(yùn)行腳本語(yǔ)言侵状,除此之外,我們還可以利用Scripting?API實(shí)現(xiàn)以下功能1毅整、暴露Java對(duì)象為腳本語(yǔ)言的全局變量2趣兄、在Java中調(diào)用腳本語(yǔ)言的方法3、腳本語(yǔ)言可以實(shí)現(xiàn)Java的接口4悼嫉、腳本語(yǔ)言可以像Java一樣使用JDK平臺(tái)下的類下面的類演示了以上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對(duì)象為腳本語(yǔ)言的全局變量??????????testInvokeScriptMethod(engine);//演示如何在Java中調(diào)用腳本語(yǔ)言的方法??????????testScriptInterface(engine);//演示腳本語(yǔ)言如何實(shí)現(xiàn)Java的接口??????????testUsingJDKClasses(engine);//演示腳本語(yǔ)言如何使用JDK平臺(tái)下的類?????}?????????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是腳本語(yǔ)言里的一個(gè)全局變量,專用于訪問JDK的package?????????Stringjs=?"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中有一個(gè)命令行工具??jrunscript艇潭,你可以在/bin下面找到這個(gè)工 具,jrunscript是一個(gè)腳本語(yǔ)言的解釋程序戏蔑,它獨(dú)立于腳本語(yǔ)言蹋凝,但默認(rèn)是用JavaScript,我們可以用jrunscript來測(cè)試自己寫的 腳本語(yǔ)言是否正確辛臊,下面是一個(gè)在命令行運(yùn)行jrunscript的簡(jiǎn)單例子
jrunscript
js>println("Hello,JrunScript");
Hello,JrunScript
js>9*8
72.0
js>
3.JTable的排序和過濾
原來的JTable基本上是只能顯示數(shù)據(jù)仙粱,在JDK6新增了對(duì)JTable的排序和過濾功能,下面代碼演示了這兩個(gè)功能
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設(shè)置排序器
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設(shè)置基于正則表達(dá)式的過濾條件
}
}
});
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);
}
}
運(yùn)行上面程序彻舰,單擊JTable的某一個(gè)title伐割,這個(gè)title對(duì)應(yīng)的列就會(huì)按照升序/降序重新排列;在下面的Criteria文本框中輸入"ese"刃唤,點(diǎn)擊"Do?Filter"按鈕隔心,JTable將只顯示帶有"ese"字符串的行,也就是China和Japan兩行尚胞,如果文本框里面什么都沒有硬霍,點(diǎn)擊"Do?Filter"按鈕,這時(shí)JTable會(huì)顯示所有的行笼裳。
4.更簡(jiǎn)單,更強(qiáng)大的JAX-WS
JAX-WS2.0的來歷
--------------------------------------------------------------------------------
JAX-WS(JSR-224)?是Java?Architecture?for?XML?Web?Services的縮寫,簡(jiǎn)單說就是一種用Java和XML開發(fā)Web?Services應(yīng)用程序的框架,?目前版本是2.0,?它是JAX-RPC?1.1的后續(xù)版本,?J2EE?1.4帶的就是JAX-RPC1.1,?而Java?EE?5里面包括了JAX-WS?2.0,但為了向后兼容,仍然支持JAX-RPC.?現(xiàn)在,SUN又把JAX-WS直接放到了Java?SE?6里面,由于JAX-WS會(huì)用到Common?Annotation(JSR?250),Java?Web?Services?Metadata(JSR?181),?JAXB2(JSR?222),?StAX(JSR?173),?所以SUN也必須把后幾個(gè)原屬于Java?EE范疇的Components下放到Java?SE,?現(xiàn)在我們可以清楚地理解了為什么Sun要把這些看似跟Java?SE沒有關(guān)系的Components放進(jìn)來,終極目的就是要在Java?SE里面支持Web?Services.
JAX-WS2.0的架構(gòu)
--------------------------------------------------------------------------------
JAX-WS不是一個(gè)孤立的框架,它依賴于眾多其他的規(guī)范,本質(zhì)上它由以下幾部分組成
1.用來開發(fā)Web?Services的Java?API
2.用來處理Marshal/Unmarshal的XML?Binding機(jī)制,JAX-WS2.0用JAXB2來處理Java?Object與XML之間的映射,Marshalling就是把Java?Object映射到XML,Unmarshalling則是把XML映射到Java?Object.之所以要做Java?Object與XML的映射,是因?yàn)樽罱K作為方法參數(shù)和返回值的Java?Object要通過網(wǎng)絡(luò)傳輸協(xié)議(一般是SOAP)傳送,這就要求必須對(duì)Java?Object做類似序列化和反序列化的工作,在SOAP中就是要用XML來表示Java?object的內(nèi)部狀態(tài)
3.眾多元數(shù)據(jù)(Annotations)會(huì)被JAX-WS用來描述Web?Services的相關(guān)類,包括Common?Annotations,?Web?Services?Metadata,?JAXB2的元數(shù)據(jù)和JAX-WS2.0規(guī)范自己的元數(shù)據(jù).
4.Annotation?Processing?Tool(APT) 是JAX-WS重要的組成部分,由于JAX-WS2.0規(guī)范用到很多元數(shù)據(jù),所以需要APT來處理眾多的Annotations. 在/bin下有兩個(gè)命令wsgen和wsimport,就是用到APT和Compiler?API來處理碰到的Annotations,wsgen可以為Web?Services?Provider產(chǎn)生并編譯必要的幫助類和相關(guān)支持文件,wsimport以WSDL作為輸入為Web?Service?Consumer產(chǎn)生并編譯必要的幫助類和相關(guān)支持文件.
5.JAX-WS還包括JAX-WS?Runtime與應(yīng)用服務(wù)器和工具之間的契約關(guān)系
JAX-WS2.0的編程模型
--------------------------------------------------------------------------------
現(xiàn)在用JAX-WS2.0來編寫Web?Services非常簡(jiǎn)單,不像JAX-RPC,JAX-WS可以把任意POJO暴露為Web?Services,服務(wù)類不需要實(shí)現(xiàn)接口,服務(wù)方法也沒有必要拋出RMI異常.下面介紹在JDK6環(huán)境下用JAX-WS2.0開發(fā)和測(cè)試Web?Services的步驟
1.編寫服務(wù)類,并用Web?Services?Metadata(JSR-181)標(biāo)注這個(gè)服務(wù)類,我用我的另一篇BlogJDK6的新特性之十:Web服務(wù)元數(shù)據(jù)中的WSProvider類作為服務(wù)類的例子,在此我重復(fù)貼一下WSProvider類的源代碼:
@WebService(targetNamespace="http://blog.csdn.net/chinajash",serviceName="HelloService")
public?class?WSProvider?{
@WebResult(name="Greetings")//自定義該方法返回值在WSDL中相關(guān)的描述
@WebMethod
public?String?sayHi(@WebParam(name="MyName")?String?name){
return?"Hi,"+name;?//@WebParam是自定義參數(shù)name在WSDL中相關(guān)的描述
}
@Oneway?//表明該服務(wù)方法是單向的,既沒有返回值,也不應(yīng)該聲明檢查異常
@WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關(guān)的描述
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()?{
//發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider這個(gè)地址,之前必須調(diào)用wsgen命令
//生成服務(wù)類WSProvider的支持類,命令如下:
//wsgen?-cp?.?WebServices.WSProvider
Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new?WSProvider());
}
}
}
2.用wsgen生成上面服務(wù)類的必要的幫助類,然后調(diào)用用EndPoint類的靜態(tài)方法publish發(fā)布服務(wù)類(步驟請(qǐng)參考我的另一篇Blog?JDK6的新特性之十:Web服務(wù)元數(shù)據(jù)),我在這里是將服務(wù)類發(fā)布到http://localhost:8888/chinajash/WSProvider
3.用wsimport為服務(wù)消費(fèi)者(也就是服務(wù)的客戶端)生成必要的幫助類,命令如下:
wsimport?http://localhost:8888/chinajash/WSProvider?wsdl
這會(huì)在<當(dāng)前目錄>\net\csdn\blog\chinajash下生成客戶端的幫助類,在這個(gè)例子中會(huì)生成7個(gè)類
HelloService.class
ObjectFactory.class
package-info.class
PrintSystemTime.class
SayHi.class
SayHiResponse.class
WSProvider.class
4.在客戶端用下面代碼即可調(diào)用步驟1定義的Web?Service
HelloService?hs?=?new?HelloService();
WSProvider?ws?=?hs.getWSProviderPort();
System.out.println(ws.sayHi("chinajash"));
ws.printSystemTime();
調(diào)用上述代碼后客戶端控制臺(tái)輸出
hi,chinajash
服務(wù)端控制臺(tái)輸出服務(wù)器當(dāng)前系統(tǒng)時(shí)間
5.輕量級(jí)Http?Server
JDK6的新特性之五:輕量級(jí)Http?Server
JDK6提供了一個(gè)簡(jiǎn)單的Http?Server?API,據(jù)此我們可以構(gòu)建自己的嵌入式Http?Server,它支持Http和Https協(xié)議,提供了HTTP1.1的部分實(shí)現(xiàn)唯卖,沒有被實(shí)現(xiàn)的那部分可以通過擴(kuò)展已有的Http?Server?API 來實(shí)現(xiàn),程序員必須自己實(shí)現(xiàn)HttpHandler接口,HttpServer會(huì)調(diào)用HttpHandler實(shí)現(xiàn)類的回調(diào)方法來處理客戶端請(qǐng)求,在這里, 我們把一個(gè)Http請(qǐng)求和它的響應(yīng)稱為一個(gè)交換,包裝成HttpExchange類,HttpServer負(fù)責(zé)將HttpExchange傳給 HttpHandler實(shí)現(xiàn)類的回調(diào)方法.下面代碼演示了怎樣創(chuàng)建自己的Http?Server
public?class?HTTPServerAPITester?{
public?static?void?main(String[]?args)?{
try?{
HttpServer?hs?=?HttpServer.create(new?InetSocketAddress(8888),0);//設(shè)置HttpServer的端口為8888
hs.createContext("/chinajash",?new?MyHandler());//用MyHandler類內(nèi)處理到/chinajash的請(qǐng)求
hs.setExecutor(null);?//?creates?a?default?executor
hs.start();
}?catch?(IOException?e)?{
e.printStackTrace();
}
}
}
class?MyHandler?implements?HttpHandler?{
public?void?handle(HttpExchange?t)?throws?IOException?{
InputStream?is?=?t.getRequestBody();
String?response?=?"
Happy?New?Year?2007!--Chinajash
";
t.sendResponseHeaders(200,?response.length());
OutputStream?os?=?t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
運(yùn)行程序后,在瀏覽器內(nèi)輸入http://localhost:8888/xx,瀏覽器輸出
6.嵌入式數(shù)據(jù)庫(kù)Derby
Derby是IBM送給開源社區(qū)的又一個(gè)禮物粱玲,是一個(gè)pure?java的數(shù)據(jù)庫(kù),現(xiàn)在已經(jīng)被列入到j(luò)ava1.6中拜轨。
不知道對(duì)于大數(shù)據(jù)量的性能如何抽减,但傳說中啟動(dòng)derby只會(huì)給JVM添加2M的內(nèi)存,對(duì)那些小數(shù)據(jù)庫(kù)應(yīng)用橄碾,比如像用access那種應(yīng)該是挺有誘惑力的卵沉。
另外,麻雀雖小法牲,五臟俱全史汗,功能要比access多得多咯,包括事務(wù)處理拒垃,并發(fā)停撞,觸發(fā)器都有,管理又簡(jiǎn)單恶复,因此自己用來做點(diǎn)工具正好合適怜森。
廢話少說,介紹一下我折騰了半天的經(jīng)驗(yàn)吧谤牡。
我的Derby配置過程:
1副硅,下載db-derby-10.1.3.1-bin.tar.gz,derby_core_plugin_10.1.3.zip和derby_ui_plugin_1.1.0.zip,把兩個(gè)插件安裝到eclipse上
2翅萤,打開ecllipse,新建一個(gè)project
3恐疲,右鍵這個(gè)project,選擇Apache?Derby套么,再選擇add?apache?derby?native培己,發(fā)現(xiàn)只是給我的project添加了幾個(gè)derby的jar,還不是在我看著順眼的lib目錄里胚泌,索性干掉省咨,換上db-derby-?10.1.3.1-bin.tar.gz解壓出來以后lib目錄下的jar文件,在Build?Path里設(shè)置一下玷室;
4零蓉,右鍵Project,在apache?derby里選擇start?apache?derby?network?server穷缤,控制臺(tái)可以看到derby啟動(dòng)后打出的“服務(wù)器準(zhǔn)備在端口?1527?上接受連接敌蜂。”
5津肛,右鍵Project章喉,在apache?derby里選擇ij(Interactive?SQL),啟動(dòng)SQL控制臺(tái);
6秸脱,輸入connect?jdbc:derby:testdb;create=true;?注意要有單引號(hào)落包,可以在工程跟目錄下創(chuàng)建testdb數(shù)據(jù)庫(kù),可以看到一個(gè)新建的目錄testdb撞反,那里的文件就是數(shù)據(jù)庫(kù)咯妥色;
7,用標(biāo)準(zhǔn)的SQL語(yǔ)句來建一個(gè)數(shù)據(jù)庫(kù)試試:
create?table?test?(a?varchar(4)?not?null,?b?char(2)?primary?key);
居然可以用遏片,太神奇了,呵呵
8撮竿,再插入一條語(yǔ)句試試呢吮便,insert?into?test(a,b)?values(a,11);,嗯幢踏,不錯(cuò)髓需,可以用select?查出來的哦。
9房蝉,再插一下:insert?into?test(a,b)?values(a,11);僚匆,哦哦,報(bào)錯(cuò)了搭幻,“錯(cuò)誤?23505:語(yǔ)句異常終止咧擂,因?yàn)樗鼘?dǎo)致“TEST”上所定義的“SQL060710092132480”標(biāo)識(shí)的唯一或主鍵約束或唯一索引中出現(xiàn)重復(fù)鍵值√刺#”?呵呵松申。
10,好了俯逾,現(xiàn)在可以像你控制的其他數(shù)據(jù)庫(kù)一樣來控制Derby了贸桶。
如果上述方法不行,或者你習(xí)慣了在eclipse之外使用和管理數(shù)據(jù)庫(kù)桌肴,那么可以很方便的把Derby“裝”在系統(tǒng)里皇筛。下面我說一下步驟:
1贮勃,把db-derby-10.1.3.1-bin.tar.gz解壓到c:\derby,使lib和framework兩個(gè)目錄在c:\derby下邊即可
2只嚣,設(shè)置環(huán)境變量
設(shè)置一個(gè)c:\derby\framework\embeded\bin或c:\derby\framework\NetworkServe\bin到Path中桩撮,這樣我們就可以直接執(zhí)行上邊介紹的connect這樣的命令而不用每次鉆到那個(gè)目錄下去執(zhí)行了
設(shè)置c:\derby\lib\derby.jar;c:\derby\lib\derbytoos.jar到CLASSPATH中沼沈,以便讓這些java編成的命令能夠正確執(zhí)行珍昨;
3挂洛,打開cmd
4佩谣,敲入startNetworkServer凡怎,可以看到像在eclisp中提示的那樣啟動(dòng)了server
5悉稠,再打開一個(gè)cmd,敲入sysinfo,可以看到derby的環(huán)境信息了宫蛆,注意在java?user?dir這一項(xiàng),也許是java用戶目錄上和上邊看到的會(huì)有所不同哦,這樣在connect?jdbc:derby:testdb;create=true;的建的數(shù)據(jù)庫(kù)目錄就不一樣咯耀盗。
6想虎,敲入ij,好了叛拷,進(jìn)入到上邊的交互界面舌厨,可以建一個(gè)數(shù)據(jù)庫(kù)看看了。
7忿薇,最后在另外一個(gè)cmd中敲入stopNetworkServer就可以關(guān)閉數(shù)據(jù)庫(kù)了裙椭。
如果你兩種方法都試過了,那么需要注意的署浩,還是上邊步驟5的問題揉燃,這個(gè)問題是你可能隨時(shí)會(huì)啟動(dòng)一個(gè)數(shù)據(jù)庫(kù)或新建一個(gè)數(shù)據(jù)庫(kù),但如果你剛剛使用derby筋栋,你可能還沒有察覺炊汤。
derby實(shí)際上有兩種啟動(dòng)方式,一種是嵌入式的弊攘,一種是網(wǎng)絡(luò)服務(wù)器的啟動(dòng)抢腐。
1,我們?cè)趀clipse中右鍵start?apache?derby?network?server那個(gè)襟交,就是網(wǎng)絡(luò)服務(wù)器的啟動(dòng)方式迈倍,在這種方式下可以用另外一臺(tái)計(jì)算機(jī)在ij中以:
connect?jdbc:derby://192.168.0.28:1527/testdb
的方式進(jìn)行鏈接。
2婿着,第二種啟動(dòng)方式是在ij里邊就直接
connect?jdbc:derby:testdb
這實(shí)際是在連當(dāng)前配置環(huán)境下java?user?dir下那個(gè)目錄的數(shù)據(jù)庫(kù)授瘦。
看到這里可能有點(diǎn)糊涂了,這么就會(huì)出問題了那竟宋?
實(shí)際上derby的訪問更像是一種使用derby?driver對(duì)本地文件系統(tǒng)的訪問提完,不管啟動(dòng)不啟動(dòng)網(wǎng)絡(luò)服務(wù)器,都可以用driver訪問本地的數(shù)據(jù)庫(kù)丘侠。這樣徒欣,在ij里邊像第二種方式那樣建立連接是完全可以的。啟動(dòng)了網(wǎng)絡(luò)服務(wù)器蜗字,只不過是能夠讓其他主機(jī)訪問罷了打肝。
另外一個(gè)問題是,在eclipse中和在系統(tǒng)中連接服務(wù)器挪捕,在connect的時(shí)候這個(gè)當(dāng)前配置環(huán)境是不一樣的粗梭,eclipse默認(rèn)工程所在路徑是數(shù)據(jù)庫(kù)的所在路徑,而在系統(tǒng)中“裝”derby則會(huì)認(rèn)為?c:\document?and?settings下邊那個(gè)用戶目錄是數(shù)據(jù)庫(kù)的所在路徑级零。
jdk1.7新特性:
1断医,switch中可以使用字串了
String?s?=?"test";
switch?(s)?{
case?"test"?:
System.out.println("test");
case?"test1"?:
System.out.println("test1");
break?;
default?:
System.out.println("break");
break?;
}
2.運(yùn)用List?tempList?=?new?ArrayList<>();?即泛型實(shí)例化類型自動(dòng)推斷
3.語(yǔ)法上支持集合,而不一定是數(shù)組
final?List?piDigits?=?[?1,2,3,4,5,8?];
4.新增一些取環(huán)境信息的工具方法
File?System.getJavaIoTempDir()?//?IO臨時(shí)文件夾
File?System.getJavaHomeDir()?//?JRE的安裝目錄
File?System.getUserHomeDir()?//?當(dāng)前用戶目錄
File?System.getUserDir()?//?啟動(dòng)java進(jìn)程時(shí)所在的目錄5
5.Boolean類型反轉(zhuǎn),空指針安全,參與位運(yùn)算
Boolean?Booleans.negate(Boolean?booleanObj)
True?=>?False?,?False?=>?True,?Null?=>?Null
boolean?Booleans.and(boolean[]?array)
boolean?Booleans.or(boolean[]?array)
boolean?Booleans.xor(boolean[]?array)
boolean?Booleans.and(Boolean[]?array)
boolean?Booleans.or(Boolean[]?array)
boolean?Booleans.xor(Boolean[]?array)
6.兩個(gè)char間的equals
boolean?Character.equalsIgnoreCase(char?ch1,?char?ch2)
7.安全的加減乘除
int?Math.safeToInt(long?value)
int?Math.safeNegate(int?value)
long?Math.safeSubtract(long?value1,?int?value2)
long?Math.safeSubtract(long?value1,?long?value2)
int?Math.safeMultiply(int?value1,?int?value2)
long?Math.safeMultiply(long?value1,?int?value2)
long?Math.safeMultiply(long?value1,?long?value2)
long?Math.safeNegate(long?value)
int?Math.safeAdd(int?value1,?int?value2)
long?Math.safeAdd(long?value1,?int?value2)
long?Math.safeAdd(long?value1,?long?value2)
int?Math.safeSubtract(int?value1,?int?value2)
8.map集合支持并發(fā)請(qǐng)求鉴嗤,且可以寫成Map?map?=?{name:"xxx",age:18};
--------------------------------------------------------------------------------------------------------------
歡迎閱讀我編寫的Java 8介紹斩启。本教程將帶領(lǐng)你一步一步地認(rèn)識(shí)這門語(yǔ)言的新特性。通過簡(jiǎn)單明了的代碼示例醉锅,你將會(huì)學(xué)習(xí)到如何使用默認(rèn)接口方法兔簇,Lambda表達(dá)式,方法引用和重復(fù)注解硬耍÷⑺觯看完這篇教程后,你還將對(duì)最新推出的API有一定的了解默垄,例如:流控制此虑,函數(shù)式接口,map擴(kuò)展和新的時(shí)間日期API等等口锭。
Java 8 允許我們使用default關(guān)鍵字,為接口聲明添加非抽象的方法實(shí)現(xiàn)介杆。這個(gè)特性又被稱為擴(kuò)展方法鹃操。下面是我們的第一個(gè)例子:
Java代碼
interfaceFormula?{
doublecalculate(inta);
defaultdoublesqrt(inta)?{
returnMath.sqrt(a);
}
}
在接口Formula中,除了抽象方法caculate以外春哨,還定義了一個(gè)默認(rèn)方法sqrt荆隘。Formula的實(shí)現(xiàn)類只需要實(shí)現(xiàn)抽象方法caculate就可以了。默認(rèn)方法sqrt可以直接使用赴背。
Java代碼
Formula?formula?=newFormula()?{
@Override
publicdoublecalculate(inta)?{
returnsqrt(a?*100);
}
};
formula.calculate(100);//?100.0
formula.sqrt(16);//?4.0
formula對(duì)象以匿名對(duì)象的形式實(shí)現(xiàn)了Formula接口椰拒。代碼很啰嗦:用了6行代碼才實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的計(jì)算功能:a*100開平方根。我們?cè)谙乱还?jié)會(huì)看到凰荚,Java 8 還有一種更加優(yōu)美的方法燃观,能夠?qū)崿F(xiàn)包含單個(gè)函數(shù)的對(duì)象。
讓我們從最簡(jiǎn)單的例子開始便瑟,來學(xué)習(xí)如何對(duì)一個(gè)string列表進(jìn)行排序缆毁。我們首先使用Java 8之前的方法來實(shí)現(xiàn):
Java代碼
List?names?=?Arrays.asList("peter","anna","mike","xenia");
Collections.sort(names,newComparator()?{
@Override
publicintcompare(String?a,?String?b)?{
returnb.compareTo(a);
}
});
靜態(tài)工具方法Collections.sort接受一個(gè)list,和一個(gè)Comparator接口作為輸入?yún)?shù)到涂,Comparator的實(shí)現(xiàn)類可 以對(duì)輸入的list中的元素進(jìn)行比較脊框。通常情況下,你可以直接用創(chuàng)建匿名Comparator對(duì)象践啄,并把它作為參數(shù)傳遞給sort方法浇雹。
除了創(chuàng)建匿名對(duì)象以外,Java 8 還提供了一種更簡(jiǎn)潔的方式屿讽,Lambda表達(dá)式昭灵。
Java代碼
Collections.sort(names,?(String?a,?String?b)?->?{
returnb.compareTo(a);
});
你可以看到,這段代碼就比之前的更加簡(jiǎn)短和易讀。但是虎锚,它還可以更加簡(jiǎn)短:
Java代碼
Collections.sort(names,?(String?a,?String?b)?->?b.compareTo(a));
只要一行代碼硫痰,包含了方法體。你甚至可以連大括號(hào)對(duì){}和return關(guān)鍵字都省略不要窜护。不過這還不是最短的寫法:
Java代碼
Collections.sort(names,?(a,?b)?->?b.compareTo(a));
Java編譯器能夠自動(dòng)識(shí)別參數(shù)的類型效斑,所以你就可以省略掉類型不寫。讓我們?cè)偕钊氲匮芯恳幌耹ambda表達(dá)式的威力吧柱徙。
Lambda表達(dá)式如何匹配Java的類型系統(tǒng)缓屠?每一個(gè)lambda都能夠通過一個(gè)特定的接口,與一個(gè)給定的類型進(jìn)行匹配护侮。一個(gè)所謂的函數(shù)式接口必須要有 且僅有一個(gè)抽象方法聲明敌完。每個(gè)與之對(duì)應(yīng)的lambda表達(dá)式必須要與抽象方法的聲明相匹配。由于默認(rèn)方法不是抽象的羊初,因此你可以在你的函數(shù)式接口里任意添 加默認(rèn)方法滨溉。
任意只包含一個(gè)抽象方法的接口,我們都可以用來做成lambda表達(dá)式长赞。為了讓你定義的接口滿足要求晦攒,你應(yīng)當(dāng)在接口前加上@FunctionalInterface 標(biāo)注。編譯器會(huì)注意到這個(gè)標(biāo)注得哆,如果你的接口中定義了第二個(gè)抽象方法的話脯颜,編譯器會(huì)拋出異常。
舉例:
Java代碼
@FunctionalInterface
interfaceConverter?{
T?convert(F?from);
}
Converter?converter?=?(from)?->?Integer.valueOf(from);
Integer?converted?=?converter.convert("123");
System.out.println(converted);//?123
注意贩据,如果你不寫@FunctionalInterface 標(biāo)注栋操,程序也是正確的。
上面的代碼實(shí)例可以通過靜態(tài)方法引用饱亮,使之更加簡(jiǎn)潔:
Java代碼
Converter?converter?=?Integer::valueOf;
Integer?converted?=?converter.convert("123");
System.out.println(converted);//?123
Java 8 允許你通過::關(guān)鍵字獲取方法或者構(gòu)造函數(shù)的的引用矾芙。上面的例子就演示了如何引用一個(gè)靜態(tài)方法。而且近尚,我們還可以對(duì)一個(gè)對(duì)象的方法進(jìn)行引用:
Java代碼
classSomething?{
String?startsWith(String?s)?{
returnString.valueOf(s.charAt(0));
}
}
Something?something?=newSomething();
Converter?converter?=?something::startsWith;
String?converted?=?converter.convert("Java");
System.out.println(converted);//?"J"
讓我們看看如何使用::關(guān)鍵字引用構(gòu)造函數(shù)蠕啄。首先我們定義一個(gè)示例bean,包含不同的構(gòu)造方法:
Java代碼
classPerson?{
String?firstName;
String?lastName;
Person()?{}
Person(String?firstName,?String?lastName)?{
this.firstName?=?firstName;
this.lastName?=?lastName;
}
}
接下來戈锻,我們定義一個(gè)person工廠接口歼跟,用來創(chuàng)建新的person對(duì)象:
Java代碼
interfacePersonFactory?{
P?create(String?firstName,?String?lastName);
}
然后我們通過構(gòu)造函數(shù)引用來把所有東西拼到一起,而不是像以前一樣格遭,通過手動(dòng)實(shí)現(xiàn)一個(gè)工廠來這么做哈街。
Java代碼
PersonFactory?personFactory?=?Person::new;
Person?person?=?personFactory.create("Peter","Parker");
我們通過Person::new來創(chuàng)建一個(gè)Person類構(gòu)造函數(shù)的引用。Java編譯器會(huì)自動(dòng)地選擇合適的構(gòu)造函數(shù)來匹配PersonFactory.create函數(shù)的簽名拒迅,并選擇正確的構(gòu)造函數(shù)形式骚秦。
對(duì)于lambdab表達(dá)式外部的變量她倘,其訪問權(quán)限的粒度與匿名對(duì)象的方式非常類似。你能夠訪問局部對(duì)應(yīng)的外部區(qū)域的局部final變量作箍,以及成員變量和靜態(tài)變量硬梁。
訪問局部變量
我們可以訪問lambda表達(dá)式外部的final局部變量:
Java代碼
finalintnum?=1;
Converter?stringConverter?=
(from)?->?String.valueOf(from?+?num);
stringConverter.convert(2);//?3
但是與匿名對(duì)象不同的是,變量num并不需要一定是final胞得。下面的代碼依然是合法的:
Java代碼
intnum?=1;
Converter?stringConverter?=
(from)?->?String.valueOf(from?+?num);
stringConverter.convert(2);//?3
然而荧止,num在編譯的時(shí)候被隱式地當(dāng)做final變量來處理。下面的代碼就不合法:
Java代碼
intnum?=1;
Converter?stringConverter?=
(from)?->?String.valueOf(from?+?num);
num?=3;
在lambda表達(dá)式內(nèi)部企圖改變num的值也是不允許的阶剑。
訪問成員變量和靜態(tài)變量
與局部變量不同跃巡,我們?cè)趌ambda表達(dá)式的內(nèi)部能獲取到對(duì)成員變量或靜態(tài)變量的讀寫權(quán)。這種訪問行為在匿名對(duì)象里是非常典型的牧愁。
Java代碼
classLambda4?{
staticintouterStaticNum;
intouterNum;
voidtestScopes()?{
Converter?stringConverter1?=?(from)?->?{
outerNum?=23;
returnString.valueOf(from);
};
Converter?stringConverter2?=?(from)?->?{
outerStaticNum?=72;
returnString.valueOf(from);
};
}
}
訪問默認(rèn)接口方法
還記得第一節(jié)里面formula的那個(gè)例子么素邪? 接口Formula定義了一個(gè)默認(rèn)的方法sqrt,該方法能夠訪問formula所有的對(duì)象實(shí)例猪半,包括匿名對(duì)象兔朦。這個(gè)對(duì)lambda表達(dá)式來講則無(wú)效。
默認(rèn)方法無(wú)法在lambda表達(dá)式內(nèi)部被訪問磨确。因此下面的代碼是無(wú)法通過編譯的:
Java代碼
Formula?formula?=?(a)?->?sqrt(?a?*100);
JDK 1.8 API中包含了很多內(nèi)置的函數(shù)式接口烘绽。有些是在以前版本的Java中大家耳熟能詳?shù)模鏑omparator接口俐填,或者Runnable接口。對(duì)這些現(xiàn) 成的接口進(jìn)行實(shí)現(xiàn)翔忽,可以通過@FunctionalInterface 標(biāo)注來啟用Lambda功能支持英融。
此外,Java 8 API 還提供了很多新的函數(shù)式接口歇式,來降低程序員的工作負(fù)擔(dān)驶悟。有些新的接口已經(jīng)在Google Guava庫(kù)中很有名了。如果你對(duì)這些庫(kù)很熟的話材失,你甚至閉上眼睛都能夠想到痕鳍,這些接口在類庫(kù)的實(shí)現(xiàn)過程中起了多么大的作用。
Predicates
Predicate是一個(gè)布爾類型的函數(shù)龙巨,該函數(shù)只有一個(gè)輸入?yún)?shù)笼呆。Predicate接口包含了多種默認(rèn)方法,用于處理復(fù)雜的邏輯動(dòng)詞(and, or旨别,negate):
Java代碼
Predicate?predicate?=?(s)?->?s.length()?>0;
predicate.test("foo");//?true
predicate.negate().test("foo");//?false
Predicate?nonNull?=?Objects::nonNull;
Predicate?isNull?=?Objects::isNull;
Predicate?isEmpty?=?String::isEmpty;
Predicate?isNotEmpty?=?isEmpty.negate();
Functions
Function接口接收一個(gè)參數(shù)诗赌,并返回單一的結(jié)果。默認(rèn)方法可以將多個(gè)函數(shù)串在一起(compse, andThen):
Java代碼
Function?toInteger?=?Integer::valueOf;
Function?backToString?=?toInteger.andThen(String::valueOf);
backToString.apply("123");//?"123"
Suppliers
Supplier接口產(chǎn)生一個(gè)給定類型的結(jié)果秸弛。與Function不同的是铭若,Supplier沒有輸入?yún)?shù)洪碳。
Java代碼
Supplier?personSupplier?=?Person::new;
personSupplier.get();//?new?Person
Consumers
Consumer代表了在一個(gè)輸入?yún)?shù)上需要進(jìn)行的操作。
Java代碼
Consumer?greeter?=?(p)?->?System.out.println("Hello,?"+?p.firstName);
greeter.accept(newPerson("Luke","Skywalker"));
Comparators
Comparator接口在早期的Java版本中非常著名叼屠。Java 8 為這個(gè)接口添加了不同的默認(rèn)方法瞳腌。
Java代碼
Comparator?comparator?=?(p1,?p2)?->?p1.firstName.compareTo(p2.firstName);
Person?p1?=newPerson("John","Doe");
Person?p2?=newPerson("Alice","Wonderland");
comparator.compare(p1,?p2);//?>?0
comparator.reversed().compare(p1,?p2);//?<?0
Optionals
Optional不是一個(gè)函數(shù)式接口,而是一個(gè)精巧的工具接口镜雨,用來防止NullPointerEception產(chǎn)生嫂侍。這個(gè)概念在下一節(jié)會(huì)顯得很重要,所以我們?cè)谶@里快速地瀏覽一下Optional的工作原理冷离。
Optional是一個(gè)簡(jiǎn)單的值容器吵冒,這個(gè)值可以是null,也可以是non-null西剥”云埽考慮到一個(gè)方法可能會(huì)返回一個(gè)non-null的值,也可能返回一個(gè)空值瞭空。為了不直接返回null揪阿,我們?cè)贘ava 8中就返回一個(gè)Optional。
Java代碼
Optional?optional?=?Optional.of("bam");
optional.isPresent();//?true
optional.get();//?"bam"
optional.orElse("fallback");//?"bam"
optional.ifPresent((s)?->?System.out.println(s.charAt(0)));//?"b"
java.util.Stream表示了某一種元素的序列咆畏,在這些元素上可以進(jìn)行各種操作南捂。Stream操作可以是中間操作,也可以是完結(jié)操作旧找。完結(jié)操作 會(huì)返回一個(gè)某種類型的值溺健,而中間操作會(huì)返回流對(duì)象本身,并且你可以通過多次調(diào)用同一個(gè)流操作方法來將操作結(jié)果串起來(就像StringBuffer的 append方法一樣————譯者注)钮蛛。Stream是在一個(gè)源的基礎(chǔ)上創(chuàng)建出來的鞭缭,例如java.util.Collection中的list或者 set(map不能作為Stream的源)。Stream操作往往可以通過順序或者并行兩種方式來執(zhí)行魏颓。
我們先了解一下序列流岭辣。首先,我們通過string類型的list的形式創(chuàng)建示例數(shù)據(jù):
Java代碼
List?stringCollection?=newArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
Java 8中的Collections類的功能已經(jīng)有所增強(qiáng)甸饱,你可以之直接通過調(diào)用Collections.stream()或者Collection.parallelStream()方法來創(chuàng)建一個(gè)流對(duì)象沦童。下面的章節(jié)會(huì)解釋這個(gè)最常用的操作。
Filter
Filter接受一個(gè)predicate接口類型的變量叹话,并將所有流對(duì)象中的元素進(jìn)行過濾偷遗。該操作是一個(gè)中間操作,因此它允許我們?cè)诜祷亟Y(jié)果的基 礎(chǔ)上再進(jìn)行其他的流操作(forEach)渣刷。ForEach接受一個(gè)function接口類型的變量鹦肿,用來執(zhí)行對(duì)每一個(gè)元素的操作。ForEach是一個(gè) 中止操作辅柴。它不返回流箩溃,所以我們不能再調(diào)用其他的流操作瞭吃。
Java代碼
stringCollection
.stream()
.filter((s)?->?s.startsWith("a"))
.forEach(System.out::println);
//?"aaa2",?"aaa1"
Sorted
Sorted是一個(gè)中間操作,能夠返回一個(gè)排過序的流對(duì)象的視圖涣旨。流對(duì)象中的元素會(huì)默認(rèn)按照自然順序進(jìn)行排序歪架,除非你自己指定一個(gè)Comparator接口來改變排序規(guī)則。
Java代碼
stringCollection
.stream()
.sorted()
.filter((s)?->?s.startsWith("a"))
.forEach(System.out::println);
//?"aaa1",?"aaa2"
一定要記住霹陡,sorted只是創(chuàng)建一個(gè)流對(duì)象排序的視圖和蚪,而不會(huì)改變?cè)瓉砑现性氐捻樞颉T瓉韘tring集合中的元素順序是沒有改變的烹棉。
Java代碼
System.out.println(stringCollection);
//?ddd2,?aaa2,?bbb1,?aaa1,?bbb3,?ccc,?bbb2,?ddd1
Map
map是一個(gè)對(duì)于流對(duì)象的中間操作攒霹,通過給定的方法,它能夠把流對(duì)象中的每一個(gè)元素對(duì)應(yīng)到另外一個(gè)對(duì)象上浆洗。下面的例子就演示了如何把每個(gè) string都轉(zhuǎn)換成大寫的string. 不但如此催束,你還可以把每一種對(duì)象映射成為其他類型。對(duì)于帶泛型結(jié)果的流對(duì)象伏社,具體的類型還要由傳遞給map的泛型方法來決定抠刺。
Java代碼
stringCollection
.stream()
.map(String::toUpperCase)
.sorted((a,?b)?->?b.compareTo(a))
.forEach(System.out::println);
//?"DDD2",?"DDD1",?"CCC",?"BBB3",?"BBB2",?"AAA2",?"AAA1"
Match
匹配操作有多種不同的類型,都是用來判斷某一種規(guī)則是否與流對(duì)象相互吻合的摘昌。所有的匹配操作都是終結(jié)操作速妖,只返回一個(gè)boolean類型的結(jié)果。
Java代碼
booleananyStartsWithA?=
stringCollection
.stream()
.anyMatch((s)?->?s.startsWith("a"));
System.out.println(anyStartsWithA);//?true
booleanallStartsWithA?=
stringCollection
.stream()
.allMatch((s)?->?s.startsWith("a"));
System.out.println(allStartsWithA);//?false
booleannoneStartsWithZ?=
stringCollection
.stream()
.noneMatch((s)?->?s.startsWith("z"));
System.out.println(noneStartsWithZ);//?true
Count
Count是一個(gè)終結(jié)操作聪黎,它的作用是返回一個(gè)數(shù)值罕容,用來標(biāo)識(shí)當(dāng)前流對(duì)象中包含的元素?cái)?shù)量。
Java代碼
longstartsWithB?=
stringCollection
.stream()
.filter((s)?->?s.startsWith("b"))
.count();
System.out.println(startsWithB);//?3
Reduce
該操作是一個(gè)終結(jié)操作稿饰,它能夠通過某一個(gè)方法杀赢,對(duì)元素進(jìn)行削減操作。該操作的結(jié)果會(huì)放在一個(gè)Optional變量里返回湘纵。
Java代碼
Optional?reduced?=
stringCollection
.stream()
.sorted()
.reduce((s1,?s2)?->?s1?+"#"+?s2);
reduced.ifPresent(System.out::println);
//?"aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"
像上面所說的,流操作可以是順序的滤淳,也可以是并行的梧喷。順序操作通過單線程執(zhí)行,而并行操作則通過多線程執(zhí)行脖咐。
下面的例子就演示了如何使用并行流進(jìn)行操作來提高運(yùn)行效率铺敌,代碼非常簡(jiǎn)單。
首先我們創(chuàng)建一個(gè)大的list屁擅,里面的元素都是唯一的:
Java代碼
intmax?=1000000;
List?values?=newArrayList<>(max);
for(inti?=0;?i?<?max;?i++)?{
UUID?uuid?=?UUID.randomUUID();
values.add(uuid.toString());
}
現(xiàn)在偿凭,我們測(cè)量一下對(duì)這個(gè)集合進(jìn)行排序所使用的時(shí)間。
順序排序
Java代碼
longt0?=?System.nanoTime();
longcount?=?values.stream().sorted().count();
System.out.println(count);
longt1?=?System.nanoTime();
longmillis?=?TimeUnit.NANOSECONDS.toMillis(t1?-?t0);
System.out.println(String.format("sequential?sort?took:?%d?ms",?millis));
//?sequential?sort?took:?899?ms
并行排序
Java代碼
longt0?=?System.nanoTime();
longcount?=?values.parallelStream().sorted().count();
System.out.println(count);
longt1?=?System.nanoTime();
longmillis?=?TimeUnit.NANOSECONDS.toMillis(t1?-?t0);
System.out.println(String.format("parallel?sort?took:?%d?ms",?millis));
//?parallel?sort?took:?472?ms
如你所見派歌,所有的代碼段幾乎都相同弯囊,唯一的不同就是把stream()改成了parallelStream(), 結(jié)果并行排序快了50%痰哨。
正如前面已經(jīng)提到的那樣,map是不支持流操作的匾嘱。而更新后的map現(xiàn)在則支持多種實(shí)用的新方法斤斧,來完成常規(guī)的任務(wù)。
Java代碼
Map?map?=newHashMap<>();
for(inti?=0;?i?<10;?i++)?{
map.putIfAbsent(i,"val"+?i);
}
map.forEach((id,?val)?->?System.out.println(val));
上面的代碼風(fēng)格是完全自解釋的:putIfAbsent避免我們將null寫入霎烙;forEach接受一個(gè)消費(fèi)者對(duì)象撬讽,從而將操作實(shí)施到每一個(gè)map中的值上。
下面的這個(gè)例子展示了如何使用函數(shù)來計(jì)算map的編碼:
Java代碼
map.computeIfPresent(3,?(num,?val)?->?val?+?num);
map.get(3);//?val33
map.computeIfPresent(9,?(num,?val)?->null);
map.containsKey(9);//?false
map.computeIfAbsent(23,?num?->"val"+?num);
map.containsKey(23);//?true
map.computeIfAbsent(3,?num?->"bam");
map.get(3);//?val33
接下來悬垃,我們將學(xué)習(xí)游昼,當(dāng)給定一個(gè)key值時(shí),如何把一個(gè)實(shí)例從對(duì)應(yīng)的key中移除:
Java代碼
map.remove(3,"val3");
map.get(3);//?val33
map.remove(3,"val33");
map.get(3);//?null
另一個(gè)有用的方法:
Java代碼
map.getOrDefault(42,"not?found");//?not?found
將map中的實(shí)例合并也是非常容易的:
Java代碼
map.merge(9,"val9",?(value,?newValue)?->?value.concat(newValue));
map.get(9);//?val9
map.merge(9,"concat",?(value,?newValue)?->?value.concat(newValue));
map.get(9);//?val9concat
合并操作先看map中是否沒有特定的key/value存在尝蠕,如果是烘豌,則把key/value存入map,否則merging函數(shù)就會(huì)被調(diào)用趟佃,對(duì)現(xiàn)有的數(shù)值進(jìn)行修改扇谣。
Java 8 包含了全新的時(shí)間日期API,這些功能都放在了java.time包下闲昭。新的時(shí)間日期API是基于Joda-Time庫(kù)開發(fā)的罐寨,但是也不盡相同。下面的例子就涵蓋了大多數(shù)新的API的重要部分序矩。
Clock
Clock提供了對(duì)當(dāng)前時(shí)間和日期的訪問功能鸯绿。Clock是對(duì)當(dāng)前時(shí)區(qū)敏感的,并可用于替代 System.currentTimeMillis()方法來獲取當(dāng)前的毫秒時(shí)間簸淀。當(dāng)前時(shí)間線上的時(shí)刻可以用Instance類來表示瓶蝴。Instance 也能夠用于創(chuàng)建原先的java.util.Date對(duì)象。
Java代碼
Clock?clock?=?Clock.systemDefaultZone();
longmillis?=?clock.millis();
Instant?instant?=?clock.instant();
Date?legacyDate?=?Date.from(instant);//?legacy?java.util.Date
Timezones
時(shí)區(qū)類可以用一個(gè)ZoneId來表示租幕。時(shí)區(qū)類的對(duì)象可以通過靜態(tài)工廠方法方便地獲取舷手。時(shí)區(qū)類還定義了一個(gè)偏移量,用來在當(dāng)前時(shí)刻或某時(shí)間與目標(biāo)時(shí)區(qū)時(shí)間之間進(jìn)行轉(zhuǎn)換劲绪。
Java代碼
System.out.println(ZoneId.getAvailableZoneIds());
//?prints?all?available?timezone?ids
ZoneId?zone1?=?ZoneId.of("Europe/Berlin");
ZoneId?zone2?=?ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
//?ZoneRules[currentStandardOffset=+01:00]
//?ZoneRules[currentStandardOffset=-03:00]
LocalTime
本地時(shí)間類表示一個(gè)沒有指定時(shí)區(qū)的時(shí)間男窟,例如,10 p.m.或者17:30:15贾富,下面的例子會(huì)用上面的例子定義的時(shí)區(qū)創(chuàng)建兩個(gè)本地時(shí)間對(duì)象歉眷。然后我們會(huì)比較兩個(gè)時(shí)間,并計(jì)算它們之間的小時(shí)和分鐘的不同颤枪。
Java代碼
LocalTime?now1?=?LocalTime.now(zone1);
LocalTime?now2?=?LocalTime.now(zone2);
System.out.println(now1.isBefore(now2));//?false
longhoursBetween?=?ChronoUnit.HOURS.between(now1,?now2);
longminutesBetween?=?ChronoUnit.MINUTES.between(now1,?now2);
System.out.println(hoursBetween);//?-3
System.out.println(minutesBetween);//?-239
LocalTime是由多個(gè)工廠方法組成汗捡,其目的是為了簡(jiǎn)化對(duì)時(shí)間對(duì)象實(shí)例的創(chuàng)建和操作,包括對(duì)時(shí)間字符串進(jìn)行解析的操作畏纲。
Java代碼
LocalTime?late?=?LocalTime.of(23,59,59);
System.out.println(late);//?23:59:59
DateTimeFormatter?germanFormatter?=
DateTimeFormatter
.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(Locale.GERMAN);
LocalTime?leetTime?=?LocalTime.parse("13:37",?germanFormatter);
System.out.println(leetTime);//?13:37
LocalDate
本地時(shí)間表示了一個(gè)獨(dú)一無(wú)二的時(shí)間扇住,例如:2014-03-11春缕。這個(gè)時(shí)間是不可變的,與LocalTime是同源的台囱。下面的例子演示了如何通過加減日淡溯,月,年等指標(biāo)來計(jì)算新的日期簿训。記住咱娶,每一次操作都會(huì)返回一個(gè)新的時(shí)間對(duì)象。
Java代碼
LocalDate?today?=?LocalDate.now();
LocalDate?tomorrow?=?today.plus(1,?ChronoUnit.DAYS);
LocalDate?yesterday?=?tomorrow.minusDays(2);
LocalDate?independenceDay?=?LocalDate.of(2014,?Month.JULY,4);
DayOfWeek?dayOfWeek?=?independenceDay.getDayOfWeek();
System.out.println(dayOfWeek);//?FRIDAYParsing?a?LocalDate?from?a?string?is?just?as?simple?as?parsing?a?LocalTime:
解析字符串并形成LocalDate對(duì)象强品,這個(gè)操作和解析LocalTime一樣簡(jiǎn)單膘侮。
Java代碼
DateTimeFormatter?germanFormatter?=
DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.GERMAN);
LocalDate?xmas?=?LocalDate.parse("24.12.2014",?germanFormatter);
System.out.println(xmas);//?2014-12-24
LocalDateTime
LocalDateTime表示的是日期-時(shí)間。它將剛才介紹的日期對(duì)象和時(shí)間對(duì)象結(jié)合起來的榛,形成了一個(gè)對(duì)象實(shí)例琼了。LocalDateTime是不可變的,與LocalTime和LocalDate的工作原理相同夫晌。我們可以通過調(diào)用方法來獲取日期時(shí)間對(duì)象中特定的數(shù)據(jù)域雕薪。
Java代碼
LocalDateTime?sylvester?=?LocalDateTime.of(2014,?Month.DECEMBER,31,23,59,59);
DayOfWeek?dayOfWeek?=?sylvester.getDayOfWeek();
System.out.println(dayOfWeek);//?WEDNESDAY
Month?month?=?sylvester.getMonth();
System.out.println(month);//?DECEMBER
longminuteOfDay?=?sylvester.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay);//?1439
如果再加上的時(shí)區(qū)信息,LocalDateTime能夠被轉(zhuǎn)換成Instance實(shí)例晓淀。Instance能夠被轉(zhuǎn)換成以前的java.util.Date對(duì)象所袁。
Java代碼
Instant?instant?=?sylvester
.atZone(ZoneId.systemDefault())
.toInstant();
Date?legacyDate?=?Date.from(instant);
System.out.println(legacyDate);//?Wed?Dec?31?23:59:59?CET?2014
格式化日期-時(shí)間對(duì)象就和格式化日期對(duì)象或者時(shí)間對(duì)象一樣。除了使用預(yù)定義的格式以外凶掰,我們還可以創(chuàng)建自定義的格式化對(duì)象燥爷,然后匹配我們自定義的格式。
Java代碼
DateTimeFormatter?formatter?=
DateTimeFormatter
.ofPattern("MMM?dd,?yyyy?-?HH:mm");
LocalDateTime?parsed?=?LocalDateTime.parse("Nov?03,?2014?-?07:13",?formatter);
String?string?=?formatter.format(parsed);
System.out.println(string);//?Nov?03,?2014?-?07:13
不同于java.text.NumberFormat懦窘,新的DateTimeFormatter類是不可變的前翎,也是線程安全的。
更多的細(xì)節(jié)畅涂,請(qǐng)看這里
Java 8中的注解是可重復(fù)的港华。讓我們直接深入看看例子,弄明白它是什么意思午衰。
首先苹丸,我們定義一個(gè)包裝注解,它包括了一個(gè)實(shí)際注解的數(shù)組
Java代碼
@interfaceHints?{
Hint[]?value();
}
@Repeatable(Hints.class)
@interfaceHint?{
String?value();
}
只要在前面加上注解名:@Repeatable苇经,Java 8 允許我們對(duì)同一類型使用多重注解:
變體1:使用注解容器(老方法):
Java代碼
@Hints({@Hint("hint1"),@Hint("hint2")})
classPerson?{}
變體2:使用可重復(fù)注解(新方法):
Java代碼
@Hint("hint1")
@Hint("hint2")
classPerson?{}
使用變體2,Java編譯器能夠在內(nèi)部自動(dòng)對(duì)@Hint進(jìn)行設(shè)置宦言。這對(duì)于通過反射來讀取注解信息來說扇单,是非常重要的。
Java代碼
Hint?hint?=?Person.class.getAnnotation(Hint.class);
System.out.println(hint);//?null
Hints?hints1?=?Person.class.getAnnotation(Hints.class);
System.out.println(hints1.value().length);//?2
Hint[]?hints2?=?Person.class.getAnnotationsByType(Hint.class);
System.out.println(hints2.length);//?2
盡管我們絕對(duì)不會(huì)在Person類上聲明@Hints注解奠旺,但是它的信息仍然可以通過getAnnotation(Hints.class)來讀 取蜘澜。并且施流,getAnnotationsByType方法會(huì)更方便,因?yàn)樗x予了所有@Hints注解標(biāo)注的方法直接的訪問權(quán)限鄙信。
Java代碼
@Target({ElementType.TYPE_PARAMETER,?ElementType.TYPE_USE})
@interfaceMyAnnotation?{}
Java 8編程指南就到此告一段落瞪醋。當(dāng)然,還有很多內(nèi)容需要進(jìn)一步研究和說明装诡。這就需要靠讀者您來對(duì)JDK 8進(jìn)行探究了银受,例如:Arrays.parallelSort, StampedLock和CompletableFuture等等 ———— 我這里只是舉幾個(gè)例子而已。
我希望這個(gè)博文能夠?qū)δ兴鶐椭徊桑蚕M喿x愉快宾巍。完整的教程源代碼放在了GitHub上。您可以盡情地fork渔伯,并請(qǐng)通過Twitter告訴我您的反饋顶霞。
原文鏈接:winterbe翻譯:ImportNew.com-黃小非
譯文鏈接:http://www.importnew.com/10360.html
------------------------------------------------------------------------------------------------------------------------------------
加快OpenJDK的開發(fā)速度:繼2014年3月份發(fā)布了java8之后,我們進(jìn)入下一個(gè)兩年的發(fā)布周期锣吼。 Java 9預(yù)計(jì)在2016年發(fā)布选浑,并且已經(jīng)公布了JEP(JDK改進(jìn)提議)中的前期列表。同時(shí)玄叠,我們已經(jīng)把一些新特性整理到了JSR(Java規(guī)范請(qǐng)求)百侧,還有提 出了一些希望包括在新版本中的其他特性。
這些重要的特性都包括在Jigsaw項(xiàng)目中谓罗。顯著的性能改善和期待已久的API包括:進(jìn)程API更新今膊,JSON將成為java.util的一部分,貨幣處理API對(duì)于想處在技術(shù)最前沿的你狐粱,可從這里獲得Java 9的初期版本舀寓。
被接受的特性
1. Jigsaw 項(xiàng)目;模塊化源碼
Jigsaw項(xiàng)目是為了模塊化Java代碼、將JRE分成可相互協(xié)作的組件肌蜻,這也是Java 9 眾多特色種的一個(gè)互墓。JEP是邁向Jigsaw四步中的第一步,它不會(huì)改變JRE和JDK的真實(shí)結(jié)構(gòu)蒋搜。JEP是為了模塊化JDK源代碼篡撵,讓編譯系統(tǒng)能夠模塊 編譯并在構(gòu)建時(shí)檢查模塊邊界。這個(gè)項(xiàng)目原本是隨Java 8發(fā)布的豆挽,但由于推遲育谬,所以將把它加到Java 9.
一旦它完成,它可能允許根據(jù)一個(gè)項(xiàng)目需求自定義組件從而減少rt.jar的大小帮哈。在JDK 7 和JDK 8的rt.jar包中有大約20,000個(gè)類膛檀,但有很多類在一些特定的環(huán)境里面并沒有被用到(即使在Java 8的緊湊分布特性中已經(jīng)包含了一部分解決方法也存在著類冗余)。這么做是為了能讓Java能夠容易應(yīng)用到小型計(jì)算設(shè)備(比如網(wǎng)絡(luò)設(shè)備)中,提高它的安全和 性能咖刃,同時(shí)也能讓開發(fā)者更容易構(gòu)建和維護(hù)這些類庫(kù)泳炉。
2. 簡(jiǎn)化進(jìn)程API
截止到目前,Java控制與管理系統(tǒng)進(jìn)程的能力是有限的嚎杨。舉個(gè)例子花鹅,現(xiàn)在為了簡(jiǎn)便獲取你程序的進(jìn)程PID,你要么調(diào)用本地程序要么要自己使用一些變通方案枫浙。更多的是刨肃,每個(gè)(系統(tǒng))平臺(tái)需要有一個(gè)不同實(shí)現(xiàn)來確保你能獲得正確的結(jié)果。
期望代碼能獲取LinuxPIDS自脯,現(xiàn)在是如下方式:
在Java 9中之景,可以變換成如下方式(支持所有的操作系統(tǒng)):
這次更新將會(huì)擴(kuò)展Java與操作系統(tǒng)的交互能力:新增一些新的直接明了的方法去處理PIDs,進(jìn)程名字和狀態(tài)以及枚舉多個(gè)JVM和進(jìn)程以及更多事情膏潮。
3. 輕量級(jí) JSON API
目前有多種處理JSON的Java工具锻狗,但JSON API 獨(dú)到之處在于JSON API將作為Java語(yǔ)言的一部分,輕量并且運(yùn)用Java 8的新特性焕参。它將放在java.util包里一起發(fā)布(但在JSR 353里面的JSON是用第三方包或者其他的方法處理的).
4. 錢和貨幣的API
在Java 8引進(jìn)了日期和時(shí)間的API之后, Java 9引入了新的貨幣API, 用以表示貨幣, 支持幣種之間的轉(zhuǎn)換和各種復(fù)雜運(yùn)算. 關(guān)于這個(gè)項(xiàng)目的具體情況, 請(qǐng)?jiān)L問https://github.com/JavaMoney,里面已經(jīng)給出了使用說明和示例, 以下是幾個(gè)重要的例子:
5. 改善鎖爭(zhēng)用機(jī)制
鎖爭(zhēng)用是限制許多Java多線程應(yīng)用性能的瓶頸. 新的機(jī)制在改善Java對(duì)象監(jiān)視器的性能方面已經(jīng)得到了多種基準(zhǔn)(benchmark)的驗(yàn)證, 其中包括Volano. 測(cè)試中通訊服務(wù)器開放了海量的進(jìn)程來連接客戶端, 其中有很多連接都申請(qǐng)同一個(gè)資源, 以此模擬重負(fù)荷日常應(yīng)用.
通過諸如此類的壓力測(cè)試我們可以估算JVM的極限吞吐量(每秒的消息數(shù)量). JEP在22種不同的測(cè)試中都得到了出色的成績(jī), 新的機(jī)制如果能在Java 9中得到應(yīng)用的話, 應(yīng)用程序的性能將會(huì)大大提升.
6. 代碼分段緩存
Java 9的另一個(gè)性能提升來自于JIT(Just-in-time)編譯器. 當(dāng)某段代碼被大量重復(fù)執(zhí)行的時(shí)候, 虛擬機(jī)會(huì)把這段代碼編譯成機(jī)器碼(native code)并儲(chǔ)存在代碼緩存里面, 進(jìn)而通過訪問緩存中不同分段的代碼來提升編譯器的效率.
和原來的單一緩存區(qū)域不同的是, 新的代碼緩存根據(jù)代碼自身的生命周期而分為三種:
永駐代碼(JVM 內(nèi)置 / 非方法代碼)
短期代碼(僅在某些條件下適用的配置性(profiled)代碼)
長(zhǎng)期代碼(非配置性代碼)
緩存分段會(huì)在各個(gè)方面提升程序的性能, 比如做垃圾回收掃描的時(shí)候可以直接跳過非方法代碼(永駐代碼), 從而提升效率.
7. 智能Java編譯, 第二階段
智能Java編譯工具sjavac的第一階段開始于JEP 139這個(gè)項(xiàng)目, 用于在多核處理器上提升JDK的編譯速度. 現(xiàn)在這個(gè)項(xiàng)目已經(jīng)進(jìn)入第二階段(JEP 199), 目的是改進(jìn)sjavac并讓其成為取代目前JDK編譯工具javac的Java默認(rèn)的通用編譯工具.
其他值得期待的內(nèi)容:
8. HTTP 2.0客戶端
HTTP 2.0標(biāo)準(zhǔn)雖然還沒正式發(fā)布, 但是已經(jīng)進(jìn)入了最終審查階段, 預(yù)計(jì)可以在Java 9發(fā)布之前審查完畢.JEP 110將會(huì)重新定義并實(shí)現(xiàn)一個(gè)全新的Java HTTP客戶端, 用來取代現(xiàn)在的HttpURLConnection, 同時(shí)也會(huì)實(shí)現(xiàn)HTTP 2.0和網(wǎng)絡(luò)接口(原文websockets). 它現(xiàn)在還沒被JEP正式認(rèn)可但我們希望在Java 9中包含這一項(xiàng)目的內(nèi)容.
官方的HTTP 2.0 RFC(Request for Comments, 官方技術(shù)討論/會(huì)議記錄等等的一系列文檔記錄)預(yù)訂于2015年2月發(fā)布, 它是基于Google發(fā)布的SPDY(Speedy, 快速的)協(xié)議. 基于SPDY協(xié)議的網(wǎng)絡(luò)相對(duì)于基于HTTP 1.1協(xié)議的網(wǎng)絡(luò)有11.81%到47.7%之間的顯著提速, 現(xiàn)在已經(jīng)有瀏覽器實(shí)現(xiàn)了這個(gè)協(xié)議.
9. Kulla計(jì)劃: Java的REPL實(shí)現(xiàn)
這個(gè)取名為Kulla的項(xiàng)目最近宣布將于2015年4月整合測(cè)試, 雖然已經(jīng)不太有希望能趕上Java 9的發(fā)布, 但如果進(jìn)度快的話或許剛好能趕上. 現(xiàn)在Java并沒有來自官方的REPL(Read-Eval-Print-Loop)方式, 也就是說現(xiàn)在如果你想要跑幾行Java代碼做一個(gè)快速的測(cè)試, 你仍然需要把這幾行代碼封裝在項(xiàng)目或者方法里面. 雖然在一些流行的IDE里面有Java REPL工具, 但它們并沒有官方支持, 而Kulla項(xiàng)目或許就能成為Java官方發(fā)布的REPL解決方案.
這些新功能出自何處轻纪?
JEP和JSR并不是無(wú)中生有,下面就介紹一下Java發(fā)展的生態(tài)環(huán)境:
小組- 對(duì)特定技術(shù)內(nèi)容, 比如安全叠纷、網(wǎng)絡(luò)刻帚、Swing、HotSpot涩嚣、有共同興趣的組織和個(gè)人崇众。
項(xiàng)目- 編寫代碼, 文檔以及其他工作,至少由一個(gè)小組贊助和支持航厚,比如最近的Lambda計(jì)劃顷歌,Jigsaw計(jì)劃和Sumatra計(jì)劃。
JDK改進(jìn)提案(JEP)- 每當(dāng)需要有新的嘗試的時(shí)候, JEP可以在JCP(Java Community Process)之前或者同時(shí)提出非正式的規(guī)范(specification)幔睬,被正是認(rèn)可的JEP正式寫進(jìn)JDK的發(fā)展路線圖并分配版本號(hào)眯漩。
Java規(guī)范提案(JSR)- 新特性的規(guī)范出現(xiàn)在這一個(gè)階段,可以來自于小組 / 項(xiàng)目麻顶、JEP赦抖、 JCP成員或者Java社區(qū)(community)成員的提案,每個(gè)Java版本都由相應(yīng)的JSR支持, Java 9暫時(shí)還沒有辅肾。