溫故而知新,重溫 Java 7 的那些「新」特性

2009 年 4 月 20 日,Java 的親生父親 Sun 被養父 Oracle 以 74 億美圓收購,這在當時但是一件天大的事。有很多同窗都擔憂 Java 的前途,我當時傻不啦嘰地也很擔憂:本身剛學會如何經過記事本編寫 Java 代碼,而後經過 cmd 打印 Hello World 呢,這一下難道白學了?java

但其實這種擔憂是多餘的,由於 Java 並不會陪葬,畢竟行業內有太多基於 Java 的軟件系統在運行,Java 牽扯了太多人的飯碗。10 年過去了,Java 果真沒有陪葬,我仍然堅守在 Java 的陣線上。程序員

2011 年 7 月 7 日,代號「海豚(Dolphin)」的 Java 7 首次推出,這也是 Java 歷史上一次很是重要的版本更新。同時推出了很是多實用的新特性,好比說建立泛型實例時自動類型推斷、switch-case 語句支持字符串類型、新增 try-with-resources 語句等等。數據庫

這麼多年過去了,Java 7 的「新」特性顯然都變成老古董了——它們彷佛也不須要我再贅述了,但好像不是這樣的。前幾天我發了一篇文章,用到了其中一個新特性,居然有同窗表示歷來沒見過這個新特性,特地在交流羣裏@我,要我說清楚怎麼回事(代碼摺疊了,隨後貼出來)。socket

當時我就在想啊,原來技術歷來沒有「新與舊」之說,只有知不知道。因此藉此機會,我就再來「贅述」一下 Java 7 的那些最常用的新特性吧。學習

0一、數值中可以使用下劃線分隔符聯接

以前圖片中的代碼沒有展現全,如今我把具體的代碼貼出來。優化

try {
	AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
	Future<Integer> result = channel.read(ByteBuffer.allocate(100_000), 0);
} catch (IOException e) {
	e.printStackTrace();
}
複製代碼

其中 100_000 就是讀者要我解釋清楚的那個特性:在數值類型的字面值中使用下劃線分隔符聯接。spa

人腦不老是很善於記住很長串的數字,因此在處理長串數字時會採用分割法,好比說電話號碼要用一個分隔符「-」隔開,銀行卡號會每隔四位有一個空格等等。code

數字中沒有用逗號(,)和中劃線(-)做爲分隔符,是由於它們可能會引起歧義,取而代之的是下劃線(_)。這個不起眼的特性,讓咱們開發人員在處理數字上輕鬆多了,畢竟 100_000100000 (忍不住查了一遍 0 的個數,懼怕多寫或者少寫)辨識度高得多。cdn

下劃線(_)位置並不固定,你能夠隨意擺放,舉例以下:對象

int a = 100_000, b = 100000, c = 10_0000;
System.out.println(a==b); // true
System.out.println(b==c); // true
System.out.println(a==c); // true
複製代碼

須要注意的是,下劃線僅僅能在數字中間,編譯器在編譯的時候本身主動刪除數字中的下劃線。反編譯後的代碼以下所示:

int a = 100000;
int b = 100000;
int c = 100000;
System.out.println(a == b);
System.out.println(b == c);
System.out.println(a == c);
複製代碼

0二、 switch-case 語句支持字符串類型

咱們都知道,switch 是一種高效的判斷語句,比起 if/else 真的是爽快多了。示例以下:

String wanger = "王二";

switch (wanger) {
case "王二":
	System.out.println("王三他哥哥王二");
	break;
case "王三":
	System.out.println("王二他弟弟王三");
	break;

default:
	System.out.println("王二他妹妹王六");
	break;
}
複製代碼

switch-case 語句在處理字符串的時候,會先將 switch 括號中的字符串和 case 後的字符串轉成 hashCode,因此字符串不能爲 null,不然會拋出 NullPointerException。反編譯後的代碼以下所示:

String wanger = "王二";
switch (wanger.hashCode()) {
	case 936926 :
		if (wanger.equals("王三")) {
			System.out.println("王二他弟弟王三");
			return;
		}
		break;
	case 937057 :
		if (wanger.equals("王二")) {
			System.out.println("王三他哥哥王二");
			return;
		}
}

System.out.println("王二他妹妹王六");
複製代碼

0三、try-with-resources 語句

try-with-resources 的基本設想是把資源(socket、文件、數據庫鏈接)的做用域限定在代碼塊內,當這塊代碼執行完後,資源會被自動釋放。

在此以前,資源的釋放須要在 finally 中主動關閉,無論 try 中的代碼是否正常退出或者異常退出。就像下面這樣:

BufferedReader in = null;
try {
	in = new BufferedReader(new FileReader("cmower.txt"));
	int charRead;
	while ((charRead = in.read()) != -1) {
		System.out.printf("%c ", (char) charRead);
	}
} catch (IOException ex) {
	ex.printStackTrace();
} finally {
	try {
		if (in != null)
			in.close();
	} catch (IOException ex) {
		ex.printStackTrace();
	}
}
複製代碼

這樣的代碼看起來就像老太婆的裹腳布,又臭又長;有了 try-with-resources 以後,狀況大有改觀,不信你看:

try (BufferedReader in = new BufferedReader(new FileReader("cmower.txt"));) {
	int charRead;
	while ((charRead = in.read()) != -1) {
		System.out.printf("%c ", (char) charRead);
	}
} catch (IOException ex) {
	ex.printStackTrace();
}
複製代碼

是否是清爽多了!把須要釋放的資源放在 try 後的 () 中,連 finally 也不須要了。不過,須要注意的是,上面的代碼還須要優化,應該爲每個資源聲明獨立的變量,不然的話,某些特殊的狀況下,資源可能沒法正常關閉。

try (FileReader fr = new FileReader("cmower.txt"); 
	BufferedReader in = new BufferedReader(fr);) {
	int charRead;
	while ((charRead = in.read()) != -1) {
		System.out.printf("%c ", (char) charRead);
	}
} catch (IOException ex) {
	ex.printStackTrace();
}
複製代碼

try-with-resources 特性依賴於一個新定義的接口 AutoCloseable,須要釋放的資源必需要實現這個接口。

不過,try-with-resources 在本質上仍然使用了 finally 去釋放資源,只不過這部分工做再也不由開發者主動去作——從反編譯後的結果能夠看得出來:

try {
	Throwable var1 = null;
	Object var2 = null;

	try {
		FileReader fr = new FileReader("cmower.txt");

		try {
			BufferedReader in = new BufferedReader(fr);

			int charRead;
			try {
				while ((charRead = in.read()) != -1) {
					System.out.printf("%c ", (char) charRead);
				}
			} finally {
				if (in != null) {
					in.close();
				}

			}
複製代碼

0四、建立泛型實例時自動類型推斷

在這個特性出現以前,有關泛型變量的聲明略顯重複,示例以下:

Map<String, ArrayList<String>> wanger = new HashMap<String, ArrayList<String>>();
複製代碼

這樣的代碼簡直太長了,不少重複的字符,難道編譯器不能推斷出泛型的類型信息嗎?Java 7 實現了這個心願。

Map<String, List<String>> wanger = new HashMap<>();
List<String> chenmo = new ArrayList<>();
wanger.put("chenmo", chenmo);
複製代碼

這個看似簡單的特性省去了很多敲擊鍵盤的次數。

0五、最後

除了上面我列出的這 4 個經常使用的新特性,Java 7 還有一些其餘的特性,好比說 multi-catch,能夠在一個 catch 語句中捕獲多個異常;好比說對集合(Collections)的加強支持,能夠直接採用 []、{} 的形式存入對象,採用 [] 的形式按照索引、鍵值來獲取集合中的對象等等。

但整體上,我列出的那 4 個特性最爲經常使用,其學習的意義更大。若是你以爲漏掉了某些更爲經常使用的特性,歡迎你在文末提出來。

歡迎關注「沉默王二」公衆號,後臺回覆關鍵字「java」便可免費獲取「Java 程序員進階必讀資料」。

相關文章
相關標籤/搜索