JDK 7 新特性小結(包含例項程式碼)

擁抱心中的夢想發表於2018-03-08

1、switch支援String做引數

/***
 * switch支援字串做引數 jdk7
 * @author huangjiawei
 */
public class SwitchTest {

	public static void switchTest(String arg) {
		
		switch (arg) {
			case "Lisa":
				System.err.println("我是Lisa!");
				break;
			case "Mike":
				System.err.println("我是Mike!");
				break;
			default:
				System.err.println("我是你的唯一!");
				break;
		}
		
	}
	
	public static void main(String[] args) {
		switchTest("Lisa");//我是Lisa!
		switchTest("Mike");//我是Mike!
		switchTest("");//我是你的唯一!
	}
	
}
複製程式碼

switch列舉支援

/**
 * switch 列舉支援 jdk5
 * @author huangjiawei
 *
 */
public class SwitchMonthTest {

	public static void SwithMonthTest(Month month) {
		
		switch (month) {
			case JANUARY:
				System.err.println("這是一月份");
				break;
			case FEBRUARY:
				System.err.println("這是二月份");
				break;
			case MARCH:
				System.err.println("這是三月份");
				break;
		}
	}
	
	public static void main(String[] args) {
		SwithMonthTest(Month.JANUARY);//這是一月份
		SwithMonthTest(Month.FEBRUARY);//這是二月份
		SwithMonthTest(Month.MARCH);//這是三月份	
	}
}
複製程式碼

2、數字字面量的改進

2.1. Java7 前支援 十進位制(1234)、八進位制(01234)、十六進位制(0x1234)   
     Java 8支援二進位制(0B11110001)
2.2. 可以使用下劃線隔開_
複製程式碼
public class BinaryTest {

	private static int a = 16;//十進位制
	private static int b = 020;//八進位制
	private static int c = 0x10;//十六進位制
	private static int d = 0b0001_0000;//二進位制,使用分隔符隔開
	
	public static void main(String[] args) {
		System.err.println(a);//16
		System.err.println(b);//16
		System.err.println(c);//16
		System.err.println(d);//16
	}
}
複製程式碼

3、資源自動關閉

在Java中,有許多的資源在使用完成之後需要對其進行關閉操作。舉個栗子,InputStream,Writer,Sockets,Connection等等。在Java 7 之前通常都是顯示呼叫其close()方法,在Java 7,你可以不用理會其是否未關閉,我們可以使用try-with-resources程式碼塊。

import java.io.BufferedReader;
import java.io.FileReader;

public class TryTest {

	
	/*
	 * 接受一個檔案的路徑 Java 7之前
	 */
	public static String tryTest(String path) {
		
		BufferedReader br = null;  
		try {  
		    br = new BufferedReader(new FileReader(path));
		    return br.readLine();
		} catch (Exception e) {
		    System.err.println("BufferedReader Exception" + e);
		} finally {
		    if (br != null) {
		        try {
		            br.close();
		            br.ready();//流已經關閉,此處丟擲異常
		        } catch (Exception e) {
		            System.err.println("BufferedReader close Exception" + e);
		        }
		    }
		}
		return "";
	}
	
	/*
	 * 接受一個檔案的路徑 Java7
	 */
	public static String tryTest1(String path) {
		/*
		 * 當try語句塊執行結束時,FileInputStream 會被自動關閉。這是因為FileInputStream 實現了java中的java.lang.AutoCloseable介面。
		 * 所有實現了這個介面的類都可以在try-with-resources結構中使用。
		 */
		try (BufferedReader br = new BufferedReader(new FileReader(path))) {  
		    return br.readLine();
		} catch (Exception e) {
		    System.err.println("BufferedReader Exception" + e);
		}
		return "";
	}
	
	public static void main(String[] args) {
		tryTest("C:\\Users\\huangjiawei\\Desktop\\my-release-key.keystore");
		tryTest1("C:\\Users\\huangjiawei\\Desktop\\my-release-key.keystore");
	}
}
複製程式碼

4、catch多個異常

Java7之前,捕獲多個異常必須有多個catch子句,在Java 7,我們可以這樣子寫:

import java.util.Date;

/**
 * 多個catch語句永遠只執行第一個匹配到的catch異常,後面有再多的catch都會被忽略掉
 * @author huangjiawei
 *
 */
public class CatchTest {

	/*
	 * java 7以前
	 */
	public static void CatchTest() {
		int a = 100;
		int b = 0;
		Date date = null;
		try {
			System.err.println(date.getTime());//這裡丟擲異常,下面的語句就不會執行啦!
			int result = a/b;//不會執行
			System.err.println(result);//不會執行
		}catch(NullPointerException e) {
			System.err.println(e);//java.lang.NullPointerException
		}catch(ArithmeticException e){
			System.err.println(e);
		}catch (Exception e) {
			System.err.println(e);
		}
	}
	/*
	 * java 7
	 */
	public static void CatchTest1() {
		int a = 100;
		int b = 0;
		Date date = null;
		try {
			int result = a/b;
			System.err.println(result);
			System.err.println(date.getTime());
		}catch(ArithmeticException | NullPointerException e) {
			System.err.println(e);//java.lang.ArithmeticException: / by zero
		}
	}
	
	public static void main(String[] args) {
		CatchTest();
		CatchTest1();
	}
}
複製程式碼

5、例項建立型別推斷

import java.util.ArrayList;
import java.util.List;

public class TypeTest {
	
	/*
	 * java 7前,前後<>都必須宣告型別
	 */
	List<String> list = new ArrayList<String>();
	
	/*
	 * java 7,後<>不須宣告型別,自動根據前面<>推斷其型別
	 */
	List<String> list1 = new ArrayList<>();
}
複製程式碼

6、增強的檔案系統

Java7 推出了全新的NIO2.0 API以此改變針對檔案管理的不便,使得在java.nio.file包下使用PathPathsFilesWatchServiceFileSystem等常用型別可以很好的簡化開發人員對檔案管理的編碼工作。

6.1 Path介面和Paths類

Path介面的某些功能其實可以和java.io包下的File類等價,當然這些功能僅限於只讀操作。在實際開發過程中,開發人員可以聯用Path介面和Paths類,從而獲取檔案的一系列上下文資訊。

  • int getNameCount(): 獲取當前檔案節點數
  • Path getFileName(): 獲取當前檔名稱
  • Path getRoot(): 獲取當前檔案根目錄
  • Path getParent(): 獲取當前檔案上級關聯目錄

聯用Path介面和Paths型別獲取檔案資訊:

import java.nio.file.Path;
import java.nio.file.Paths;

public class PathPathsTest {
	public static void main(String[] args) {
		Path path = Paths.get("C:\\\\Users\\\\huangjiawei\\\\Desktop\\\\my-release-key.keystore");
		System.out.println("檔案節點數:" + path.getNameCount());  //檔案節點數:4
		System.out.println("檔名稱:" + path.getFileName());  //檔名稱:my-release-key.keystore
		System.out.println("檔案根目錄:" + path.getRoot());  //檔案根目錄:C:\
		System.out.println("檔案上級關聯目錄:" + path.getParent());//檔案上級關聯目錄:C:\Users\huangjiawei\Desktop
	}
}
複製程式碼

6.2. Files類

聯用Path介面和Paths類可以很方便的訪問到目標檔案的上下文資訊。當然這些操作全都是隻讀的,如果開發人員想對檔案進行其它非只讀操作,比如檔案的建立、修改、刪除等操作,則可以使用Files型別進行操作。

Files型別常用方法如下:

  • Path createFile(): 在指定的目標目錄建立新檔案

  • void delete(): 刪除指定目標路徑的檔案或資料夾

  • Path copy(): 將指定目標路徑的檔案拷貝到另一個檔案中

  • Path move(): 將指定目標路徑的檔案轉移到其他路徑下,並刪除原始檔 使用Files型別複製、貼上檔案示例:

    Files.copy(Paths.get("/test/src.xml"), Paths.get("/test/target.xml"));

使用Files型別來管理檔案,相對於傳統的I/O方式來說更加方便和簡單。因為具體的操作實現將全部移交給NIO2.0 API,開發人員則無需關注。

6.3. WatchService

Java7 還為開發人員提供了一套全新的檔案系統功能,那就是檔案監測。在此或許有很多朋友並不知曉檔案監測有何意義及目,那麼請大家回想下除錯成熱釋出功能後的Web容器。當專案迭代後並重新部署時,開發人員無需對其進行手動重啟,因為Web容器一旦監測到檔案發生改變後,便會自動去適應這些“變化”並重新進行內部裝載。Web容器的熱釋出功能同樣也是基於檔案監測功能,所以不得不承認,檔案監測功能的出現對於Java檔案系統來說是具有重大意義的。

檔案監測是基於事件驅動的,事件觸發是作為監測的先決條件。開發人員可以使用java.nio.file包下的StandardWatchEventKinds型別提供的3種字面常量來定義監測事件型別,值得注意的是監測事件需要和WatchService例項一起進行註冊。

StandardWatchEventKinds型別提供的監測事件:

  • ENTRY_CREATE:檔案或資料夾新建事件;
  • ENTRY_DELETE:檔案或資料夾刪除事件;
  • ENTRY_MODIFY:檔案或資料夾貼上事件;

使用WatchService類實現檔案監控完整示例:

import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

/**
 * 檔案監控系統
 * @author huangjiawei
 */
public class WatchViewTest {
	public static void testWatch() {  
	    /* 監控目標路徑 */
	    Path path = Paths.get("C:\\Users\\huangjiawei\\Desktop");
	    try {
	        /* 建立檔案監控物件. */
	        WatchService watchService = FileSystems.getDefault().newWatchService();

	        /* 註冊檔案監控的所有事件型別. */
	        path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
	                StandardWatchEventKinds.ENTRY_MODIFY);

	        /* 迴圈監測檔案. */
	        while (true) {
	            WatchKey watchKey = watchService.take();

	            /* 迭代觸發事件的所有檔案 */
	            for (WatchEvent<?> event : watchKey.pollEvents()) {
	                System.out.println(event.context().toString() + " 事件型別:" + event.kind());
	            }

	            if (!watchKey.reset()) {
	                return;
	            }
	        }
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	}
	public static void main(String[] args) {
		testWatch();
	}
}
複製程式碼

通過上述程式示例我們可以看出,使用WatchService介面進行檔案監控非常簡單和方便。首先我們需要定義好目標監控路徑,然後呼叫FileSystems型別的newWatchService()方法建立WatchService物件。接下來我們還需使用Path介面的register()方法註冊WatchService例項及監控事件。當這些基礎作業層全部準備好後,我們再編寫外圍實時監測迴圈。最後迭代WatchKey來獲取所有觸發監控事件的檔案即可。

現在我終於知道,spring boot中那個所謂的dev-tools熱更新的基本原理啦!原來JDK都有提供這樣的API。


參考資料:

Java7的新特性

Java7的新特性1

相關文章