jdk8已經出來好長時間了,這裏本身學習時簡單總結的jdk5,jdk6和jdk7的新特性:
本文提綱:java
一.jdk5的新特性程序員
二.jdk6的新特性數據庫
三.jdk7的新特性編程
首先簡單介紹一下各類特性及其使用安全
1.泛型(Generic)
C++經過模板技術能夠指定集合的元素類型,而Java在1.5以前一直沒有相對應的功能。一個集合能夠聽任何類型的對象,服務器
相應地從集合裏面拿對象的時候咱們也不得不對他們進行強制得類型轉換。猛虎引入了泛型,它容許指定集網絡
Collection<String> c = new ArrayList(); c.add(new Date()); 編譯器會給出一個錯誤: add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)
A、類型安全併發
拋棄List、Map,使用List<T>、Map<K,V>給它們添加元素或者使用Iterator<T>遍歷時,編譯期就能夠給你檢查出類型錯誤app
B、方法參數和返回值加上了Type框架
拋棄List、Map,使用List<T>、Map<K,V>
C、不須要類型轉換
List<String> list=new ArrayList<String>();
String str=list.get(i);
D、類型通配符「?」
假設一個打印List<T>中元素的方法printList,咱們但願任何類型T的List<T>均可以被打印:
代碼:
public void printList(List<?> list,PrintStream out)throws IOException{ for(Iterator<?> i=list.iterator();i.hasNext();){ System.out.println(i.next.toString()); } }
若是通配符?讓咱們的參數類型過於普遍,咱們能夠把List<?>、Iterator<?> 修改成
List<? Extends Number>、Iterator<? Extends Number>限制一下它。
2.For-Each循環
For-Each循環得加入簡化了集合的遍歷。假設咱們要遍歷一個集合對其中的元素進行一些處理。典型的代碼爲:
void processAll(Collection c){ for(Iterator i=c.iterator(); i.hasNext();){ MyClass myObject = (MyClass)i.next(); myObject.process(); } } #使用For-Each循環,咱們能夠把代碼改寫成: void processAll(Collection<MyClass> c){ for (MyClass myObject :c) myObject.process(); }
這段代碼要比上面清晰許多,而且避免了強制類型轉換。
3.自動裝包/拆包(Autoboxing/unboxing)
自動裝包/拆包大大方便了基本類型數據和它們包裝類地使用。
自動裝包:基本類型自動轉爲包裝類.(int >> Integer)
自動拆包:包裝類自動轉爲基本類型.(Integer >> int)
在JDK1.5以前,咱們老是對集合不能存放基本類型而耿耿於懷,如今自動轉換機制解決了咱們的問題。
4.枚舉(Enums)
JDK1.5加入了一個全新類型的「類」-枚舉類型。爲此JDK1.5引入了一個新關鍵字enmu,咱們能夠這樣來定義一個枚舉類型。
public enum Color{ Red, White, Blue } #而後能夠這樣來使用Color myColor = Color.Red. #枚舉類型還提供了兩個有用的靜態方法values()和valueOf(). 咱們能夠很方便地使用它們,例如 for (Color c : Color.values()) System.out.println(c);
5.可變參數(Varargs)
可變參數使程序員能夠聲明一個接受可變數目參數的方法。注意,可變參數必須是函數聲明中的最後一個參數。
假設咱們要寫一個簡單的方法打印一些對象,
在JDK1.5以前,咱們能夠用重載來實現,可是這樣就須要寫不少的重載函數,顯得不是頗有效。
若是使用可變參數的話咱們只須要一個函數就好了.
public void write(Object... objs) { for (Object obj: objs) System.out.println(obj); }
在引入可變參數之後,Java的 反射包也更加方便使用了。對於c.getMethod
("test", new Object[0]).invoke(c.newInstance(), new Object[0])),
如今咱們能夠這樣寫了c.getMethod("test").invoke(c.newInstance()),這樣的代碼比 原來清楚了不少。
6.靜態導入(Static Imports)
要使用用靜態成員(方法和變量)咱們必須給出提供這個方法的類。使用靜態導入可使被導入類的全部靜態變量和靜態方法在當前類直接可見,
使用這些靜態成員無需再給出他們的類名。
import static java.lang.Math.*; …….
r = sin(PI * 2); //無需再寫r = Math.sin(Math.PI);
可是,過分使用這個特性也會必定程度上下降代碼地可讀性。
6.Annotations 它是java中的metadata
A.Tiger中預約義的三種標準annotation
(1).Override 方法重載
指出某個method覆蓋了superclass 的method當你要覆蓋的方法名拼寫錯時編譯不經過
(2).Deprecated 方法過期
指出某個method或element類型的使用是被阻止的,子類將不能覆蓋該方法
(3).SupressWarnings 編譯器警告
關閉class、method、field、variable 初始化的編譯期警告,好比:List沒有使用 Generic,則@SuppressWarnings("unchecked")去掉編譯期警告。
B.自定義annotation
public @interface Marked{}
C.meta-annotation
或者說annotation的annotation
四種標準的meta-annotation所有定義在java.lang.annotaion包中:
Target
指定所定義的annotation能夠用在哪些程序單元上
若是Target沒有指定,則表示該annotation可使用在任意程序單元上
代碼
@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE}) public @interface TODO {}
Annotation的反射
咱們發現java.lang.Class有許多與Annotation的反射相關的方法,如getAnnotations、isAnnotationpresent
咱們能夠利用Annotation反射來作許多事情,好比自定義Annotation來作Model對象驗證
代碼
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface RejectEmpty { /** hint title used in error message */ String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD, ElementType.METHOD }) public @interface AcceptInt { int min() default Integer.MIN_VALUE; int max() default Integer.MAX_VALUE; String hint() default ""; }
使用@RejectEmpty和@AcceptInt標註咱們的Model的field,而後利用反射來作Model驗證
7.新的格式化方法(java.util.Formatter)
formatter.format("Remaining account balance: $%.2f", balance);
8.新的線程模型和併發庫Thread Framework
HashMap的替代者ConcurrentHashMap和ArrayList的替代者CopyOnWriteArrayList
在大併發量讀取時採用java.util.concurrent包裏的一些類會讓你們滿意BlockingQueue、Callable、Executor、Semaphore...
1.引入了一個支持腳本引擎的新框架
2.UI的加強
3.對WebService支持的加強(JAX-WS2.0和JAXB2.0)
4.一系列新的安全相關的加強
5.JDBC4.0
6.Compiler API
7.通用的Annotations支持
1.二進制字面量
JDK7開始,終於能夠用二進制來表示整數(byte,short,int和long)。使用二進制字面量的好處是,能夠是
代碼更容易被理解。語法很是簡單,只要在二進制數值前面加0b或者0B
byte nByte = (byte)0b0001; short nShort = (short)0B0010; int nInt = 0b0011; long nLong = 0b0100L;
2.數字字面量能夠出現下劃線
對於一些比較大的數字,咱們定義起來老是不方面,常常缺乏或者增長位數。JDK7爲咱們提供了一種解決
方案,下劃線能夠出如今數字字面量。
int a = 10_0000_0000; long b = 0xffff_ffff_ffff_ffffl; byte c = 0b0001_1000;
注意:你只能將下劃線置於數字之間,如下使用方法是錯誤的,
(1).數字的開頭或者結尾
(2).小數點的先後
(3).‘F’或者‘f’的後綴
(4).只能用數字的位置
int err1 = _11,err2=11_; float err3=3._4,err4=3_.4; long err5=0x888_f;
3.switch 語句能夠用字符串了
private static void switchString(String str){ switch(str){ case "one": System.err.println("1"); break; case "two": System.out.println("2"); break; default : System.out.println("err"); } }
4.泛型實例的建立能夠經過類型推斷來簡化
之後你建立一個泛型實例,不須要再詳細說明類型,只需用<>,編譯器會自動幫你匹配
#例如
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
#能夠簡化爲
Map<String, List<String>> myMap = new HashMap<>();
5.在可變參數方法中傳遞非具體化參數(Non-Reifiable Formal Parameters),改進編譯警告和錯誤
有些參數類型,例如ArrayList<Number> 和List<String>,是非具體化的(non-reifiable).在編譯階段,
編譯器會擦除該類型信息。
Heap pollution 指一個變量被指向另一個不是相同類型的變量。例如
List l = new ArrayList<Number>(); List<String> ls = l; // unchecked warning l.add(0, new Integer(42)); // another unchecked warning String s = ls.get(0); // ClassCastException is thrown
回到咱們的主題,在jdk7中,當你定義下面的函數時
public static <T> void addToList (List<T> listArg, T... elements) { for (T x : elements) { listArg.add(x); } }
你會獲得一個warning
warning: [varargs] Possible heap pollution from parameterized vararg type
在jdk7以前,當你調用一個含有非具體化參數的可變參數方法,你必須自行保證不會發生「heap
pollution」。這有一個問題,若是調用者對方法不熟悉,他根本沒法判斷。JDK7對此作了改進,在該方法被定
義時久發出警告
1.加 annotation @SafeVarargs 2.加 annotation @SuppressWarnings({"unchecked", "varargs"}) 3.使用編譯器參數 –Xlint:varargs;
6.try-with-resources 語句
jdk7提供了try-with-resources,能夠自動關閉相關的資源(只要該資源實現了AutoCloseable接口,jdk7爲絕
大部分資源對象都實現了這個接口)
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }
try 語句塊中還能夠同時處理多個資源,能夠跟普通的try語句同樣catch異常,有finally語句塊
try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) ) { }catch(…){ }finally{ }
7.Catch多個Exception,rethrow exception 改進了類型檢測
不少時候,咱們捕獲了多個異常,卻作了相同的事情,好比記日誌,包裝成新的異常,而後rethrow。這
時,代碼就不那麼優雅了,例如
catch (IOException ex) { logger.log(ex); throw ex; catch (SQLException ex) { logger.log(ex); throw ex; }
Jdk7容許捕獲多個異常
catch (IOException|SQLException ex) { logger.log(ex); throw ex; }
注意,catch後面的異常參數是final的,不能從新再複製
當你從新拋出多個異常時,再也不須要詳細定義異常類型了,編譯器已經知道你具體拋出的是哪一個異常了。你
只需在方法定義的時候聲明須要拋出的異常便可
public void call() throws ReflectiveOperationException, IOException { try { callWithReflection(arg); } catch (final Exception e) { logger.trace("Exception in reflection", e); throw e; } }
8.JDBC4.1更新了兩個新特性
1. Connection,ResultSet 和Statement 都實現了Closeable 接口,全部在try-with-resources 語句中調
用,就能夠自動關閉相關資源了
try (Statement stmt = con.createStatement()){ … }
2. RowSet 1.1:引入RowSetFactory接口和RowSetProvider類,能夠建立JDBC driver支持的各類row sets
RowSetFactory myRowSetFactory = null; JdbcRowSet jdbcRs = null; ResultSet rs = null; Statement stmt = null; try { myRowSetFactory = RowSetProvider.newFactory();//用缺省的RowSetFactory 實現 jdbcRs = myRowSetFactory.createJdbcRowSet(); //建立一個 JdbcRowSet 對象,配置數據庫鏈接屬性 jdbcRs.setUrl("jdbc:myDriver:myAttribute"); jdbcRs.setUsername(username); jdbcRs.setPassword(password); jdbcRs.setCommand("select ID from TEST");
jdbcRs.execute();
}
RowSetFactory 接口包括了建立不一樣類型的RowSet的方法
createCachedRowSet
createFilteredRowSet
createJdbcRowSet
createJoinRowSet
createWebRowSet
9.更新了NIO2.0文件系統
java.io.File 不夠完美吧。Jdk7提供了一套新的文件系統,會讓你滿意的。
先來聊聊java.io.File的七宗罪吧:)
1.不少方法失敗時候都沒有拋出異常,很難查找緣由
2.方法 rename 在不一樣平臺中運行有問題
3.不能真正支持 symbolic links
4.不能讀取文件的更詳細屬性,好比權限,全部者……
5.訪問 文件的 metadata 效率低下
6.不少方法性能不行。例如處理比較大的目錄
7.沒法遞歸查找文件樹,以及存在循環的symbolic links可能形成問題
主要包括:
FileSystem 提供了許多方法來得到當前文件系統的相關信息。
Path 處理路徑(文件和目錄),包括
建立path,Paths.get(String s)
得到path的詳細信息 getName(),getXX()…
刪除path的冗餘信息 toRealPath
轉換path toAbsolutePath()
合併兩個path resolve()
在兩個path之間建立相對路徑 relativeze()
比較路徑 equal() startsWith(),endWith()
Files 支持各類文件操做,包括
移動文件,
複製文件,
刪除文件,
更詳細的文件屬性,包括文件權限,建立者,修改時間……
Walking the File Tree(遞歸遍歷文件樹)
Watch a Directory for Change (監聽文件更改)
9.異步IO AIO
概述JDK7引入了Asynchronous I/O。I/O編程中,經常使用到兩種模式:Reactor 和Proactor。Reactor就是Java的NIO。當有事件觸發時,咱們獲得通知,進行相應的處理。Proactor就是咱們今天要講的AIO了。AIO進行I/O操做,都是異步處理,當事件完成時,咱們會獲得通知。JDK7的AIO包括網絡和文件操做。二者大同小異,本文經過一個完整的客戶端/服務器Sample來詳細說明aio的網絡操做。AIO提供了兩種異步操做的監聽機制。第一種經過返回一個Future對象來事件,調用其get()會等到操做完成。第二種相似於回調函數。在進行異步操做時,傳遞一個CompletionHandler,當異步操做結束時,會調用CompletionHandler.complete 接口