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 核心知识整理&面试资料。