Java 平臺自出現到目前爲止,已經 20 多個年頭了,這 20 多年間 Java 也一直做爲最流行的程序設計語言之一,不斷面臨着其餘新興編程語言的挑戰與衝擊。Java 語言是一種靜態強類型語言,這樣的語言特性可讓 Java 編譯器在編譯階段發現錯誤,這對於構建出一個穩定安全且健壯的應用來講,尤其重要。可是也由於這種特性,讓 Java 開發彷佛變得缺乏靈活性,開發某些功能的應用時,代碼量多是其餘語言的幾倍。Java 開發的不足之處也體現愈來愈複雜的 JDK 上,愈來愈複雜的 JDK 讓開發者徹底理解的難度變的很是大。以致於開發者有時會重複實現一個 JDK 中已經提供了的功能。java
爲了跟上互聯網應用編程發展的腳步, Java 從 9 版本開始調整了 JDK 發佈的節奏,JDK 的每次更新都注重提升生產效率,提升 JVM 性能,推行模塊化等,讓開發者能夠更多的專一於業務自己,而不是浪費過多的時間在語言特性上。 Java 語言的更新要在語言的嚴謹性和靈活性上找到一個平衡點,畢竟靈活性能夠減小編碼的複雜度,而嚴謹性是構建複雜且健壯應用的基石。mysql
Java 重要的更新版本是在 Java 5 版本,這個版本中增長了如泛型、加強 for、自動裝箱拆箱、枚舉類型,可變參數、註解等一系列重要功能,可是隨後的 Java 6 中並無增長新的重要的語言特性。Java 5 的發佈是在 2004 年,已經好久遠了,網上關於 Java 的教程也大可能是基於 Java 6 的,也所以我準備從 Java 7 開始介紹每一個 Java 版本的新特性。面試
下面全部代碼的運行演示都是基於 Java 7 ,因此你若是嘗試下面的代碼,須要安裝並配置 Jdk 1.7 或者已上版本。sql
在 Java 7 以前,switch 語法中只支持整數類型以及這些整數類型的封裝類進行判斷,在 Java 7 中,支持了 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 以後能夠直接定義字符串名稱。網絡
可是這個支持只是編譯器層面的支持, JVM 依舊是不支持的。在對字符串進行 switch 時,編譯器會把字符串轉換成整數類型再進行判斷。爲了驗證上面說的只是編譯器層面的支持,咱們反編譯(可使用 Jad 反編譯工具,也能夠在 Idea 中雙擊編譯生成的 class )生成的 class 文件,看到編譯器把 switch string 轉換成了字符串 hashCode 判斷,爲了防止 hashCode 衝突,又使用了 equals 再次判斷。oracle
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("你好");
}
}
}複製代碼
Java 不一樣於 C++,須要開發者本身管理每一塊內存,大多時候 Java 虛擬機均可以很好的幫咱們進行資源管理,可是也有時候須要手動釋放一些資源,好比數據庫鏈接、磁盤文件鏈接、網絡鏈接等。換句話說,只要是資源數量有限的,都須要咱們手動的進行釋放。編程語言
在操做有限資源的時候,可能會出現各類異常,不論是讀取階段仍是在最後關閉資源的過程當中,都有可能出現問題,咱們一般會使用下面的方式 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
時發生了異常而已。
上面的問題在 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
,稱爲抑制異常,後續文章會詳細介紹。
在 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 捕獲多個異常時,不能出現重複的異常類型,也不能出現一個異常類型是另外一個類的子類的狀況。
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複製代碼
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複製代碼
雖然 Java 7 早在 2011 年就已經發布了,可是據我發現,使用到 Java 7 開始的新特性新語法的並很少,因此個人 JDK 新特性系列文章計劃從 Java 7 開始,一直介紹到目前已經發布的 Java 13,之後 Java 新版本更新的同時,這個新特性系列文章也會持續更新。
此去山高水遠,願能一路堅持,願你我一路同行。
<完>
我的網站:www.codingme.net
若是你喜歡這篇文章,能夠關注公衆號,一塊兒成長。
關注公衆號回覆資源能夠沒有套路的獲取全網最火的的 Java 核心知識整理&面試資料。