java基礎(1)-比較jdk5,jdk6,jdk7的新特性


jdk8已經出來好長時間了,這里自己學習時簡單總結的jdk5,jdk6和jdk7的新特性:
本文提綱:

一.jdk5的新特性

二.jdk6的新特性

三.jdk7的新特性

一.jdk5的新特性

首先簡單介紹一下各種特性及其使用

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>遍歷時,編譯期就可以給你檢查出類型錯誤

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...

二.jdk6的新特性

1.引入了一個支持腳本引擎的新框架

2.UI的增強

3.對WebService支持的增強(JAX-WS2.0和JAXB2.0)

4.一系列新的安全相關的增強

5.JDBC4.0

6.Compiler API

7.通用的Annotations支持

 

三.jdk7的新特性

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 接口

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM