JDK各個版本的新特性
對於很多剛接觸java語言的初學者來說,要了解一門語言,最好的方式就是要能從基礎的版本進行了解,升級的過程,以及升級的新特性,這樣才能循序漸進的學好一門語言。今天先為大家介紹一下JDK1.5版本到JDK1.7版本的特性。希望能給予幫助。
JDK1.5新特性:
1.自動裝箱與拆箱:
自動裝箱的過程:每當需要一種型別的物件時,這種基本型別就自動地封裝到與它相同型別的包裝中。
自動拆箱的過程:每當需要一個值時,被裝箱物件中的值就被自動地提取出來,沒必要再去呼叫intValue()和doubleValue()方法。
自動裝箱,只需將該值賦給一個型別包裝器引用,java會自動建立一個物件。
自動拆箱,只需將該物件值賦給一個基本型別即可。
java——類的包裝器
型別包裝器有:Double,Float,Long,Integer,Short,Character和Boolean
2.列舉
把集合裡的物件元素一個一個提取出來。列舉型別使程式碼更具可讀性,理解清晰,易於維護。列舉型別是強型別的,從而保證了系統安全性。而以類的靜態欄位實現的類似替代模型,不具有列舉的簡單性和型別安全性。
簡單的用法:JavaEnum簡單的用法一般用於代表一組常用常量,可用來代表一類相同型別的常量值。
複雜用法:Java為列舉型別提供了一些內建的方法,同事列舉常量還可以有自己的方法。可以很方便的遍歷列舉物件。
3.靜態匯入
通過使用 import static,就可以不用指定
importxxxx 和import static xxxx的區別是前者一般匯入的是類檔案如import java.util.Scanner;後者一般是匯入靜態的方法,import staticjava.lang.System.out。
4.可變引數(Varargs)
可變引數的簡單語法格式為:
methodName([argumentList],dataType...argumentName);
5.內省(Introspector)
是 Java語言對Bean類屬性、事件的一種預設處理方法。例如類A中有屬性name,那我們可以通過getName,setName
一般的做法是通過類Introspector來獲取某個物件的BeanInfo資訊,然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然後我們就可以通過反射機制來呼叫這些方法。
6.泛型(Generic)
C++通過模板技術可以指定集合的元素型別,而Java在1.5之前一直沒有相對應的功能。一個集合可以放任何型別的物件,相應地從集合裡面拿物件的時候我們也不得不對他們進行強制得型別轉換。猛虎引入了泛型,它允許指定集合裡元素的型別,這樣你可以得到強型別在編譯時刻進行型別檢查的好處。
7.For-Each迴圈
For-Each迴圈得加入簡化了集合的遍歷。假設我們要遍歷一個集合對其中的元素進行一些處理。
JDK 1.6新特性(轉)
有關JDK1.6的新特性reamerit的部落格文章已經說的很詳細了。
1.Desktop類和SystemTray類
在JDK6中,AWT新增加了兩個類:Desktop和SystemTray。
前者可以用來開啟系統預設瀏覽器瀏覽指定的URL,開啟系統預設郵件客戶端給指定的郵箱發郵件,用預設應用程式開啟或編輯檔案(比如,用記事本開啟以txt為字尾名的檔案),用系統預設的印表機列印文件;後者可以用來在系統托盤區建立一個托盤程式.
2.使用JAXB2來實現物件與XML之間的對映
JAXB是JavaArchitecture for XML Binding的縮寫,可以將一個Java物件轉變成為XML格式,反之亦然。
我們把物件與關係資料庫之間的對映稱為ORM, 其實也可以把物件與XML之間的對映稱為OXM(Object XML Mapping). 原來JAXB是JavaEE的一部分,在JDK6中,SUN將其放到了Java SE中,這也是SUN的一貫做法。JDK6中自帶的這個JAXB版本是2.0, 比起1.0(JSR 31)來,JAXB2(JSR 222)用JDK5的新特性Annotation來標識要作繫結的類和屬性等,這就極大簡化了開發的工作量。
實際上,在Java EE 5.0中,EJB和WebServices也通過Annotation來簡化開發工作。另外,JAXB2在底層是用StAX(JSR173)來處理XML文件。除了JAXB之外,我們還可以通過XMLBeans和Castor等來實現同樣的功能。
3.理解StAX
StAX(JSR173)是JDK6.0中除了DOM和SAX之外的又一種處理XML文件的API。
StAX的來歷:在JAXP1.3(JSR206)有兩種處理XML文件的方法:DOM(Document Object Model)和SAX(Simple API for XML).
由於JDK6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都會用到StAX所以Sun決定把StAX加入到JAXP家族當中來,並將JAXP的版本升級到1.4(JAXP1.4是JAXP1.3的維護版本).JDK6裡面JAXP的版本就是1.4.。
StAX是TheStreaming API for XML的縮寫,一種利用拉模式解析(pull-parsing)XML文件的API.StAX通過提供一種基於事件迭代器(Iterator)的API讓程式設計師去控制xml文件解析過程,程式遍歷這個事件迭代器去處理每一個解析事件,解析事件可以看做是程式拉出來的,也就是程式促使解析器產生一個解析事件然後處理該事件,之後又促使解析器產生下一個解析事件,如此迴圈直到碰到文件結束符;
SAX也是基於事件處理xml文件,但卻是用推模式解析,解析器解析完整個xml文件後,才產生解析事件,然後推給程式去處理這些事件;DOM 採用的方式是將整個xml文件對映到一顆記憶體樹,這樣就可以很容易地得到父節點和子結點以及兄弟節點的資料,但如果文件很大,將會嚴重影響效能。
4.使用CompilerAPI
現在我們可以用JDK6 的Compiler API(JSR 199)去動態編譯Java原始檔,CompilerAPI結合反射功能就可以實現動態的產生Java程式碼並編譯執行這些程式碼,有點動態語言的特徵。
這個特性對於某些需要用到動態編譯的應用程式相當有用,比如JSPWeb Server,當我們手動修改JSP後,是不希望需要重啟Web Server才可以看到效果的,這時候我們就可以用Compiler API來實現動態編譯JSP檔案,當然,現在的JSPWeb Server也是支援JSP熱部署的,現在的JSP Web Server通過在執行期間通過Runtime.exec或ProcessBuilder來呼叫javac來編譯程式碼,這種方式需要我們產生另一個程序去做編譯工作,不夠優雅而且容易使程式碼依賴與特定的作業系統;Compiler API通過一套易用的標準的API提供了更加豐富的方式去做動態編譯,而且是跨平臺的。
5.輕量級HttpServer API
JDK6提供了一個簡單的Http Server API,據此我們可以構建自己的嵌入式Http Server,它支援Http和Https協議,提供了HTTP1.1的部分實現,沒有被實現的那部分可以通過擴充套件已有的Http Server API來實現,程式設計師必須自己實現HttpHandler介面,HttpServer會呼叫HttpHandler實現類的回撥方法來處理客戶端請求,在這裡,我們把一個Http請求和它的響應稱為一個交換,包裝成HttpExchange類,HttpServer負責將HttpExchange傳給HttpHandler實現類的回撥方法.
6.插入式註解處理API(PluggableAnnotation Processing API)
插入式註解處理API(JSR 269)提供一套標準API來處理Annotations(JSR175)
實際上JSR 269不僅僅用來處理Annotation,我覺得更強大的功能是它建立了Java 語言本身的一個模型,它把method,package, constructor, type, variable, enum, annotation等Java語言元素對映為Types和Elements(兩者有什麼區別?),從而將Java語言的語義對映成為物件,我們可以在javax.lang.model包下面可以看到這些類. 所以我們可以利用JSR269提供的API來構建一個功能豐富的超程式設計(metaprogramming)環境.
JSR269用AnnotationProcessor在編譯期間而不是執行期間處理Annotation, Annotation Processor相當於編譯器的一個外掛,所以稱為插入式註解處理.如果Annotation Processor處理Annotation時(執行process方法)產生了新的Java程式碼,編譯器會再呼叫一次AnnotationProcessor,如果第二次處理還有新程式碼產生,就會接著呼叫Annotation Processor,直到沒有新程式碼產生為止.每執行一次process()方法被稱為一個"round",這樣整個Annotationprocessing過程可以看作是一個round的序列.
JSR269主要被設計成為針對Tools或者容器的API. 舉個例子,我們想建立一套基於Annotation的單元測試框架(如TestNG),在測試類裡面用Annotation來標識測試期間需要執行的測試方法。
7.用Console開發控制檯程式
JDK6中提供了java.io.Console類專用來訪問基於字元的控制檯裝置. 你的程式如果要與Windows下的cmd或者Linux下的Terminal互動,就可以用Console類代勞. 但我們不總是能得到可用的Console, 一個JVM是否有可用的Console依賴於底層平臺和JVM如何被呼叫. 如果JVM是在互動式命令列(比如Windows的cmd)中啟動的,並且輸入輸出沒有重定向到另外的地方,那麼就可以得到一個可用的Console實例.
8.對指令碼語言的支援如:ruby, groovy, javascript.
9.CommonAnnotations
Commonannotations原本是Java EE 5.0(JSR 244)規範的一部分,現在SUN把它的一部分放到了JavaSE 6.0中.
隨著Annotation元資料功能(JSR 175)加入到JavaSE 5.0裡面,很多Java 技術(比如EJB,Web Services)都會用Annotation部分代替XML檔案來配置執行引數(或者說是支援宣告式程式設計,如EJB的宣告式事務), 如果這些技術為通用目的都單獨定義了自己的Annotations,顯然有點重複建設, 所以,為其他相關的Java技術定義一套公共的Annotation是有價值的,可以避免重複建設的同時,也保證Java SE和Java EE 各種技術的一致性.
下面列舉出Common Annotations 1.0裡面的10個AnnotationsCommon Annotations
AnnotationRetention Target Description
GeneratedSource ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE,PARAMETER, TYPE 用於標註生成的原始碼
ResourceRuntime TYPE, METHOD, FIELD 用於標註所依賴的資源,容器據此注入外部資源依賴,有基於欄位的注入和基於setter方法的注入兩種方式
ResourcesRuntime TYPE 同時標註多個外部依賴,容器會把所有這些外部依賴注入
PostConstructRuntime METHOD 標註當容器注入所有依賴之後執行的方法,用來進行依賴注入後的初始化工作,只有一個方法可以標註為PostConstruct
PreDestroyRuntime METHOD 當物件例項將要被從容器當中刪掉之前,要執行的回撥方法要標註為PreDestroy RunAs Runtime TYPE 用於標註用什麼安全形色來執行被標註類的方法,這個安全形色必須和Container的Security角色一致的。RolesAllowedRuntime TYPE, METHOD 用於標註允許執行被標註類或方法的安全形色,這個安全形色必須和Container 的Security角色一致的
PermitAllRuntime TYPE, METHOD 允許所有角色執行被標註的類或方法
DenyAllRuntime TYPE, METHOD 不允許任何角色執行被標註的類或方法,表明該類或方法不能在Java EE容器裡面執行
DeclareRolesRuntime TYPE 用來定義可以被應用程式檢驗的安全形色,通常用isUserInRole來檢驗安全形色
注意:
1.RolesAllowed,PermitAll,DenyAll不能同時應用到一個類或方法上
2.標註在方法上的RolesAllowed,PermitAll,DenyAll會覆蓋標註在類上的RolesAllowed,PermitAll,DenyAll
3.RunAs,RolesAllowed,PermitAll,DenyAll和DeclareRoles還沒有加到JavaSE 6.0上來
4.處理以上Annotations的工作是由JavaEE容器來做,Java SE 6.0只是包含了上面表格的前五種Annotations的定義類,並沒有包含處理這些Annotations的引擎,這個工作可以由PluggableAnnotation Processing API(JSR 269)來做
改動的地方最大的就是java GUI介面的顯示了,JDK6.0(也就是JDK1.6)支援最新的windowsvista系統的WindowsAero視窗效果,而JDK1.5不支援!!!
你要在vista環境下程式設計的話最好裝jdk6.0,否則它總是換到windowsbasic視窗效果.
JDK 1.7 新特性(轉)
1.對Java集合(Collections)的增強支援
在JDK1.7之前的版本中,Java集合容器中存取元素的形式如下:
以List、Set、Map集合容器為例:
在JDK1.7中,摒棄了Java集合介面的實現類,如:ArrayList、HashSet和HashMap。而是直接採用[]、{}的形式存入物件,採用[]的形式按照索引、鍵值來獲取集合中的物件,如下:
2.在Switch中可用String
在之前的版本中是不支援在Switch語句塊中用String型別的資料的,這個功能在C#語言中早已被支援,好在JDK1.7中加入了。
3.數值可加下劃線
例如:int one_million = 1_000_000;
4.支援二進位制文字
例如:int binary = 0b1001_1001;
5.簡化了可變引數方法的呼叫
當程式設計師試圖使用一個不可具體化的可變引數並呼叫一個*varargs* (可變)方法時,編輯器會生成一個“非安全操作”的警告。
原文:http://iteye.blog.163.com/blog/static/18630809620127136516641/?suggestedreading&wumii
jAVA8 十大新特性
投稿:junjie 字型:[增加減小]型別:轉載
本教程將Java8的新特新逐一列出,並將使用簡單的程式碼示例來指導你如何使用預設介面方法,lambda表示式,方法引用以及多重Annotation,之後你將會學到最新的API上的改進,比如流,函式式介面,Map以及全新的日期API
“Java is still not dead—and people are starting to figure thatout.”
本教程將用帶註釋的簡單程式碼來描述新特性,你將看不到大片嚇人的文字。
一、介面的預設方法
Java 8允許我們給介面新增一個非抽象的方法實現,只需要使用 default關鍵字即可,這個特徵又叫做擴充套件方法,示例如下:
程式碼如下:
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
Formula介面在擁有calculate方法之外同時還定義了sqrt方法,實現了Formula介面的子類只需要實現一個calculate方法,預設方法sqrt將在子類上可以直接使用。
程式碼如下:
Formula formula = new Formula() {
@Override
public double calculate(int a) {
return sqrt(a * 100);
}
};
formula.calculate(100); // 100.0
formula.sqrt(16); // 4.0
文中的formula被實現為一個匿名類的例項,該程式碼非常容易理解,6行程式碼實現了計算 sqrt(a * 100)。在下一節中,我們將會看到實現單方法介面的更簡單的做法。
譯者注:在Java中只有單繼承,如果要讓一個類賦予新的特性,通常是使用介面來實現,在C++中支援多繼承,允許一個子類同時具有多個父類的介面與功能,在其他語言中,讓一個類同時具有其他的可複用程式碼的方法叫做mixin。新的Java 8 的這個特新在編譯器實現的角度上來說更加接近Scala的trait。在C#中也有名為擴充套件方法的概念,允許給已存在的型別擴充套件方法,和Java 8的這個在語義上有差別。二、Lambda 表示式首先看看在老版本的Java中是如何排列字串的:
複製程式碼程式碼如下:
List<String> names = Arrays.asList("peter", "anna","mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
只需要給靜態方法 Collections.sort 傳入一個List物件以及一個比較器來按指定順序排列。通常做法都是建立一個匿名的比較器物件然後將其傳遞給sort方法。
在Java 8 中你就沒必要使用這種傳統的匿名物件的方式了,Java 8提供了更簡潔的語法,lambda表示式:
複製程式碼程式碼如下:
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
看到了吧,程式碼變得更段且更具有可讀性,但是實際上還可以寫得更短:
複製程式碼程式碼如下:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
對於函式體只有一行程式碼的,你可以去掉大括號{}以及return關鍵字,但是你還可以寫得更短點:
複製程式碼程式碼如下:
Collections.sort(names, (a, b) -> b.compareTo(a));
Java編譯器可以自動推匯出引數型別,所以你可以不用再寫一次型別。接下來我們看看lambda表示式還能作出什麼更方便的東西來:三、函式式介面
Lambda 表示式是如何在java的型別系統中表示的呢?每一個lambda表示式都對應一個型別,通常是介面型別。而“函式式介面”是指僅僅只包含一個抽象方法的介面,每一個該型別的lambda表示式都會被匹配到這個抽象方法。因為預設方法不算抽象方法,所以你也可以給你的函式式介面新增預設方法。
我們可以將lambda表示式當作任意只包含一個抽象方法的介面型別,確保你的介面一定達到這個要求,你只需要給你的介面新增 @FunctionalInterface 註解,編譯器如果發現你標註了這個註解的介面有多於一個抽象方法的時候會報錯的。
示例如下:
複製程式碼程式碼如下:
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Converter<String, Integer> converter = (from) ->Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123
需要注意如果@FunctionalInterface如果沒有指定,上面的程式碼也是對的。
譯者注將lambda表示式對映到一個單方法的介面上,這種做法在Java 8之前就有別的語言實現,比如Rhino JavaScript直譯器,如果一個函式引數接收一個單方法的介面而你傳遞的是一個function,Rhino 直譯器會自動做一個單介面的例項到function的介面卡,典型的應用場景有org.w3c.dom.events.EventTarget 的addEventListener第二個引數 EventListener。
四、方法與建構函式引用前一節中的程式碼還可以通過靜態方法引用來表示:
複製程式碼程式碼如下:
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123
Java 8 允許你使用 :: 關鍵字來傳遞方法或者建構函式引用,上面的程式碼展示瞭如何引用一個靜態方法,我們也可以引用一個物件的方法:
複製程式碼程式碼如下:
converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted); // "J"
接下來看看建構函式是如何使用::關鍵字來引用的,首先我們定義一個包含多個建構函式的簡單類:
複製程式碼程式碼如下:
class Person {
String firstName;
String lastName;
Person() {}
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
接下來我們指定一個用來建立Person物件的物件工廠介面:
複製程式碼程式碼如下:
interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}
這裡我們使用建構函式引用來將他們關聯起來,而不是實現一個完整的工廠:
複製程式碼程式碼如下:
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");
我們只需要使用 Person::new 來獲取Person類建構函式的引用,Java編譯器會自動根據PersonFactory.create方法的簽名來選擇合適的建構函式。
五、Lambda 作用域在lambda表示式中訪問外層作用域和老版本的匿名物件中的方式很相似。你可以直接訪問標記了final的外層區域性變數,或者例項的欄位以及靜態變數。
六、訪問區域性變數
我們可以直接在lambda表示式中訪問外層的區域性變數:
複製程式碼程式碼如下:
final int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from +num);
stringConverter.convert(2); // 3
但是和匿名物件不同的是,這裡的變數num可以不用宣告為final,該程式碼同樣正確:
複製程式碼程式碼如下:
int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from +num);
stringConverter.convert(2); // 3
不過這裡的num必須不可被後面的程式碼修改(即隱性的具有final的語義),例如下面的就無法編譯:
複製程式碼程式碼如下:
int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from +num);
num = 3;
在lambda表示式中試圖修改num同樣是不允許的。七、訪問物件欄位與靜態變數
和本地變數不同的是,lambda內部對於例項的欄位以及靜態變數是即可讀又可寫。該行為和匿名物件是一致的:
複製程式碼程式碼如下:
classLambda4 {
static int outerStaticNum;
int outerNum;
void testScopes() {
Converter<Integer, String>stringConverter1 = (from) -> {
outerNum =23;
returnString.valueOf(from);
};
Converter<Integer,String> stringConverter2 = (from) -> {
outerStaticNum = 72;
returnString.valueOf(from);
};
}
}
八、訪問介面的預設方法還記得第一節中的