點贊再看,動力無限。Hello world : ) 微信搜「 程序猿阿朗 」。
本文 Github.com/niumoo/JavaNotes 和 未讀代碼博客 已經收錄,有很多知識點和系列文章。
前言
Java 平台自出現到目前為止,已經 20 多個年頭了,這 20 多年間 Java 也一直作為最流行的程序設計語言之一,不斷面臨着其他新興編程語言的挑戰與沖擊。Java 語言是一種靜態強類型語言,這樣的語言特性可以讓 Java 編譯器在編譯階段發現錯誤,這對於構建出一個穩定安全且健壯的應用來說,尤為重要。但是也因為這種特性,讓 Java 開發似乎變得缺少靈活性,開發某些功能的應用時,代碼量可能是其他語言的幾倍。Java 開發的不足之處也體現越來越復雜的 JDK 上,越來越復雜的 JDK 讓開發者完全理解的難度變的非常大。以至於開發者有時會重復實現一個 JDK 中已經提供了的功能。
為了跟上互聯網應用編程發展的腳步, Java 從 9 版本開始調整了 JDK 發布的節奏,JDK 的每次更新都注重提高生產效率,提高 JVM 性能,推行模塊化等,讓開發者可以更多的專注於業務本身,而不是浪費過多的時間在語言特性上。 Java 語言的更新要在語言的嚴謹性和靈活性上找到一個平衡點,畢竟靈活性可以減少編碼的復雜度,而嚴謹性是構建復雜且健壯應用的基石。
Java 7 語言特性
Java 重要的更新版本是在 Java 5 版本,這個版本中增加了如泛型、增強 for、自動裝箱拆箱、枚舉類型,可變參數、注解等一系列重要功能,但是隨后的 Java 6 中並沒有增加新的重要的語言特性。Java 5 的發布是在 2004 年,已經很久遠了,網上關於 Java 的教程也大多是基於 Java 6 的,也因此我准備從 Java 7 開始介紹每個 Java 版本的新特性。
下面所有代碼的運行演示都是基於 Java 7 ,所以你如果嘗試下面的代碼,需要安裝並配置 Jdk 1.7 或者已上版本。
1. switch String
在 Java 7 之前,switch 語法中只支持整數類型以及這些整數類型的封裝類進行判斷,在 Java 7 中,支持了 string 字符串類型的判斷,使用起來非常的簡單,但是實用性是很高的。
1.1. switch String 基本用法
編寫一個簡單的 switch 判斷字符串的測試類。
public class SwitchWithString {
public static void main(String[] args) {
String gender = "男";
System.out.println(gender.hashCode());
switch (gender) {
case "男":
System.out.println("先生你好");
break;
case "女":
System.out.println("女士你好");
break;
default:
System.out.println("你好");
}
}
}
switch 判斷字符串使用起來很簡單,結果也顯而易見會先輸出 gender 變量的 hashCode,然后輸出匹配結果“先生你好”。
30007
先生你好
在使用 switch string 時候,如果結合 Java 5 的枚舉類,那么效果會更好,Java 7 之前使用枚舉類要為每個值編數字代號,Java 7 之后可以直接定義字符串名稱。
1.2. switch String 實現原理
但是這個支持只是編譯器層面的支持, JVM 依舊是不支持的。在對字符串進行 switch 時,編譯器會把字符串轉換成整數類型再進行判斷。為了驗證上面說的只是編譯器層面的支持,我們反編譯(可以使用 Jad 反編譯工具,也可以在 Idea 中雙擊編譯生成的 class )生成的 class 文件,看到編譯器把 switch string 轉換成了字符串 hashCode 判斷,為了防止 hashCode 沖突,又使用了 equals 再次判斷。
public class SwitchWithString {
public SwitchWithString() {
}
public static void main(String[] args) {
String gender = "男";
System.out.println(gender.hashCode());
byte var3 = -1;
switch(gender.hashCode()) {
case 22899:
if (gender.equals("女")) {
var3 = 1;
}
break;
case 30007:
if (gender.equals("男")) {
var3 = 0;
}
}
switch(var3) {
case 0:
System.out.println("先生你好");
break;
case 1:
System.out.println("女士你好");
break;
default:
System.out.println("你好");
}
}
}
2. try-with-resource
Java 不同於 C++,需要開發者自己管理每一塊內存,大多時候 Java 虛擬機都可以很好的幫我們進行資源管理,但是也有時候需要手動釋放一些資源,比如數據庫連接、磁盤文件連接、網絡連接等。換句話說,只要是資源數量有限的,都需要我們手動的進行釋放。
2.1. try-catch-finally
在操作有限資源的時候,可能會出現各種異常,不管是讀取階段還是在最后關閉資源的過程中,都有可能出現問題,我們通常會使用下面的方式 try-catch-finally
保證資源的釋放。
像下面這樣。
/**
* 釋放資源
*
* @author www.codingme.net
*/
public class TryCatachFinally {
/**
* 異常處理
*
* @param args
*/
public static void main(String[] args) throws Exception {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("jdk-feature-7.iml");
} catch (FileNotFoundException e) {
throw e;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw e;
}
}
}
}
}
看看這惡心的代碼結構,為了捕獲異常,我們寫了一個 catch
,為了能保證釋放資源,我們又寫了 finally
進行資源釋放,在資源釋放時為了捕捉 close
時拋出的異常,我們又寫了一個 try-catch
。最后看着這復雜的代碼,如果有人告訴你這段代碼有 bug
,那你一定不會相信。但是確實是這樣,看起來嚴密的代碼邏輯,當 try
中的代碼邏輯和 close
方法同時產生異常的時候,try
中的異常信息會丟失。
可以看這里例子。
package net.codingme.feature.jdk7;
import java.io.IOException;
/**
* 釋放資源
*
* @author www.codingme.net
*/
public class TryCatachFinallyThrow {
/**
* 異常處理
*
* @param args
*/
public static void main(String[] args) throws Exception {
read();
}
public static void read() throws Exception {
FileRead fileRead = null;
try {
fileRead = new FileRead();
fileRead.read();
} catch (Exception e) {
throw e;
} finally {
if (fileRead != null) {
try {
fileRead.close();
} catch (Exception e) {
throw e;
}
}
}
}
}
class FileRead {
public void read() throws Exception {
throw new IOException("讀取異常");
}
public void close() throws Exception {
System.out.println("資源關閉");
throw new IOException("關閉異常");
}
}
很明顯代碼里 read
和 close
方法都會產生異常,但是運行程序發現只能收到 close
的異常信息。
資源關閉
Exception in thread "main" java.io.IOException: 關閉異常
at net.codingme.feature.jdk7.FileRead.close(TryCatachFinallyThrow.java:51)
at net.codingme.feature.jdk7.TryCatachFinallyThrow.read(TryCatachFinallyThrow.java:33)
at net.codingme.feature.jdk7.TryCatachFinallyThrow.main(TryCatachFinallyThrow.java:20)
異常信息丟失了,可怕的是你以為只是 close
時發生了異常而已。
2.2. try-autocloseable
上面的問題在 Java 7 中其實已經提供了新的解決方式,Java 7 中對 try
進行了增強,可以保證資源總能被正確釋放 。使用增強 try
的前提是 try
中的類實現了 AutoCloseable
接口,在 Java 7 中大量的需要釋放資源的操作其實都已經實現了此接口了。
實現了 AutoCloseable
的類,在增強 try
中使用時,不用擔心資源的關閉,在使用完畢會自動的調用 close
方法,並且異常不會丟失。
讓我們編寫的模擬資源操作的類實現 AutoCloseable
接口,然后時候增強 try
看看效果。
package net.codingme.feature.jdk7;
/**
* 自動關閉
*
* @author www.codingme.net
*/
public class AutoCloseResource {
public static void main(String[] args) throws Exception {
try (Mysql mysql = new Mysql();
OracleDatabase oracleDatabase = new OracleDatabase()) {
mysql.conn();
oracleDatabase.conn();
}
}
}
class Mysql implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("mysql 已關閉");
}
public void conn() {
System.out.println("mysql 已連接");
}
}
class OracleDatabase implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("OracleDatabase 已關閉");
}
public void conn() {
System.out.println("OracleDatabase 已連接");
}
}
測試類 Mysql 和 OracleDatabase 都是實現了 AutoCloseable,運行查看結果。
mysql 已連接
OracleDatabase 已連接
OracleDatabase 已關閉
mysql 已關閉
確認在發生異常時候異常信息不會丟失,寫一個有異常的模擬測試類進行測試。
package net.codingme.feature.jdk7;
import java.io.IOException;
/**
* 釋放資源
*
* @author www.codingme.net
*/
public class AutoCloseThrow {
public static void main(String[] args) throws Exception {
try (FileReadAutoClose fileRead = new FileReadAutoClose()) {
fileRead.read();
}
}
}
class FileReadAutoClose implements AutoCloseable {
public void read() throws Exception {
System.out.println("資源讀取");
throw new IOException("讀取異常");
}
@Override
public void close() throws Exception {
System.out.println("資源關閉");
throw new IOException("關閉異常");
}
}
運行查看異常信息。
資源讀取
資源關閉
Exception in thread "main" java.io.IOException: 讀取異常
at net.codingme.feature.jdk7.FileReadAutoClose.read(AutoCloseThrow.java:23)
at net.codingme.feature.jdk7.AutoCloseThrow.main(AutoCloseThrow.java:14)
Suppressed: java.io.IOException: 關閉異常
at net.codingme.feature.jdk7.FileReadAutoClose.close(AutoCloseThrow.java:29)
at net.codingme.feature.jdk7.AutoCloseThrow.main(AutoCloseThrow.java:15)
自動關閉,異常清晰,關閉異常存在於 Suppressed
,稱為抑制異常,后續文章會詳細介紹。
3. try-catch
在 Java 7 之前,一個 catch 只能捕獲一個異常信息,當異常種類非常多的時候就很麻煩,但是在 Java 7 中,一個 catch 可以捕獲多個異常信息,每個異常捕獲之間使用 |
分割,
package net.codingme.feature.jdk7;
import java.io.IOException;
/**
* 多異常捕獲
*/
public class TryCatchMany {
public static void main(String[] args) {
try (TxtRead txtRead = new TxtRead()) {
txtRead.reader();
} catch (IOException | NoSuchFieldException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class TxtRead implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("資源釋放");
}
public void reader() throws IOException, NoSuchFieldException {
System.out.println("數據讀取");
}
}
需要注意的是,一個 catch 捕獲多個異常時,不能出現重復的異常類型,也不能出現一個異常類型是另一個類的子類的情況。
4. 二進制
Java 7 開始,可以直接指定不同的進制數字。
- 二進制指定數字值,只需要使用
0b
或者OB
開頭。 - 八進制指定數字值,使用
0
開頭。 - 十六進制指定數字值,使用
0x
開頭。
/**
* 二進制
*
* @author www.codingme.net
*/
public class Binary {
public static void main(String[] args) {
// 二進制
System.out.println("------2進制-----");
int a = 0b001;
int b = 0b010;
System.out.println(a);
System.out.println(b);
// 八進制
System.out.println("------8進制-----");
int a1 = 010;
int b1 = 020;
System.out.println(a1);
System.out.println(b1);
// 十六進制
System.out.println("------16進制-----");
int a2 = 0x10;
int b2 = 0x20;
System.out.println(a2);
System.out.println(b2);
}
}
輸出結果。
------2進制-----
1
2
------8進制-----
8
16
------16進制-----
16
32
5. 數字下划線
Java 7 開始支持在數字定義時候使用下划線分割,增加了數字的可讀性。
/**
* 數字下環線
*
* @author www.codingme.net
*/
public class NumberLine {
public static void main(String[] args) {
int a = 1_000;
int b = 1_0__0_0_0_____00;
System.out.println(a);
System.out.println(b);
}
}
得到結果。
1000
1000000
6. 結束語
雖然 Java 7 早在 2011 年就已經發布了,但是據我發現,使用到 Java 7 開始的新特性新語法的並不多,所以我的 JDK 新特性系列文章計划從 Java 7 開始,一直介紹到目前已經發布的 Java 13,以后 Java 新版本更新的同時,這個新特性系列文章也會持續更新。
此去山高水遠,願能一路堅持,願你我一路同行。
<完>
Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。
點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。
文章持續更新,可以關注公眾號「 程序猿阿朗 」或訪問「未讀代碼博客 」。
回復【資料】有我准備的各系列知識點和必看書籍。
本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。