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 的那些最常用的新特性吧。学习
以前图片中的代码没有展现全,如今我把具体的代码贴出来。优化
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_000
比 100000
(忍不住查了一遍 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);
复制代码
咱们都知道,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("王二他妹妹王六");
复制代码
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();
}
}
复制代码
在这个特性出现以前,有关泛型变量的声明略显重复,示例以下:
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);
复制代码
这个看似简单的特性省去了很多敲击键盘的次数。
除了上面我列出的这 4 个经常使用的新特性,Java 7 还有一些其余的特性,好比说 multi-catch,能够在一个 catch 语句中捕获多个异常;好比说对集合(Collections)的加强支持,能够直接采用 []、{} 的形式存入对象,采用 [] 的形式按照索引、键值来获取集合中的对象等等。
但整体上,我列出的那 4 个特性最为经常使用,其学习的意义更大。若是你以为漏掉了某些更为经常使用的特性,欢迎你在文末提出来。
欢迎关注「沉默王二」公众号,后台回复关键字「java」便可免费获取「Java 程序员进阶必读资料」。