温故而知新,重温 Java 7 的那些“新”特性
2009 年 4 月 20 日,Java 的亲生父亲 Sun 被养父 Oracle 以 74 亿美元收购,这在当时可是一件天大的事。有不少同学都担心 Java 的前途,我当时傻不啦叽地也很担心:自己刚学会如何通过记事本编写 Java 代码,然后通过 cmd 打印 Hello World 呢,这一下难道白学了?
但其实这种担心是多余的,因为 Java 并不会陪葬,毕竟行业内有太多基于 Java 的软件系统在运行,Java 牵扯了太多人的饭碗。10 年过去了,Java 果然没有陪葬,我仍然坚守在 Java 的阵线上。
2011 年 7 月 7 日,代号「海豚(Dolphin)」的 Java 7 首次推出,这也是 Java 历史上一次非常重要的版本更新。同时推出了非常多实用的新特性,比如说创建泛型实例时自动类型推断、switch-case 语句支持字符串类型、新增 try-with-resources 语句等等。
这么多年过去了,Java 7 的“新”特性显然都变成老古董了——它们似乎也不需要我再赘述了,但好像不是这样的。前几天我发了一篇文章,用到了其中一个新特性,竟然有同学表示从来没见过这个新特性,特意在交流群里@我,要我说清楚怎么回事(代码折叠了,随后贴出来)。
当时我就在想啊,原来技术从来没有“新与旧”之说,只有知不知道。所以借此机会,我就再来“赘述”一下 Java 7 的那些最经常使用的新特性吧。
01、数值中可使用下划线分隔符联接
之前图片中的代码没有展示全,现在我把具体的代码贴出来。
try {
AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
Future<Integer> result = channel.read(ByteBuffer.allocate(100_000), 0);
} catch (IOException e) {
e.printStackTrace();
}
其中 100_000
就是读者要我解释清楚的那个特性:在数值类型的字面值中使用下划线分隔符联接。
人脑不总是很善于记住很长串的数字,所以在处理长串数字时会采用分割法,比如说电话号码要用一个分隔符“-”隔开,银行卡号会每隔四位有一个空格等等。
数字中没有用逗号(,)和中划线(-)作为分隔符,是因为它们可能会引发歧义,取而代之的是下划线(_)。这个不起眼的特性,让我们开发人员在处理数字上轻松多了,毕竟 100_000
比 100000
(忍不住查了一遍 0 的个数,害怕多写或者少写)辨识度高得多。
下划线(_)位置并不固定,你可以随意摆放,举例如下:
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);
02、 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("王二他妹妹王六");
03、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();
}
}
04、创建泛型实例时自动类型推断
在这个特性出现之前,有关泛型变量的声明略显重复,示例如下:
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);
这个看似简单的特性省去了不少敲击键盘的次数。
05、最后
除了上面我列出的这 4 个常用的新特性,Java 7 还有一些其他的特性,比如说 multi-catch,可以在一个 catch 语句中捕获多个异常;比如说对集合(Collections)的增强支持,可以直接采用 []、{} 的形式存入对象,采用 [] 的形式按照索引、键值来获取集合中的对象等等。
但总体上,我列出的那 4 个特性最为常用,其学习的意义更大。如果你觉得漏掉了某些更为常用的特性,欢迎你在文末提出来。
温故而知新,重温 Java 7 的那些“新”特性的更多相关文章
- JAVA JDK1.5-1.9新特性
1.51.自动装箱与拆箱:2.枚举(常用来设计单例模式)3.静态导入4.可变参数5.内省 1.61.Web服务元数据2.脚本语言支持3.JTable的排序和过滤4.更简单,更强大的JAX-WS5.轻量 ...
- Java 8 正式发布,新特性全搜罗
经过2年半的努力.屡次的延期和9个里程碑版本,甲骨文的Java开发团队终于发布了Java 8正式版本. Java 8版本最大的改进就是Lambda表达式,其目的是使Java更易于为多核处理器编写代码: ...
- Java引入的一些新特性
Java引入的一些新特性 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程, ...
- 使用示例带你提前了解 Java 9 中的新特性
使用示例带你提前了解 Java 9 中的新特性 转载来源:https://juejin.im/post/58c5e402128fe100603cc194 英文出处:https://www.journa ...
- Java学习之==>Java8 新特性详解
一.简介 Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.Java 8是 Java 自 Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库. ...
- JAVA笔记 之 JDK新特性
JDK1.5新特性1.泛型(Generics) 为集合(collections)提供编译时类型安全,无需每刻从Collections取得一个对象就进行强制转换(cast) 2.增强的for循环(for ...
- Java系列 - 用Java8新特性进行Java开发太爽了
本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome/ 前言 从开始写博客到现在已经过去3个 ...
- Java系列 – 用Java8新特性进行Java开发太爽了(续)
本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome-2/ 前言 上周, 我们谈论了关于Ja ...
- Java各个版本的新特性
原链接:http://blog.csdn.net/shareus/article/details/50736159 1.5 1.自动装箱与拆箱: 2.枚举(常用来设计单例模式) http://www. ...
随机推荐
- 数组Array
数组Array是最基本的数据结构,在内存中为一段定长连续内存,很多编程语言都有实现. 一.一维数组 下面代码实现了一维数组和它的遍历. clear并非清空数组,而是采用具体值对数组进行初始化. imp ...
- PhpStorm 配置 PHPUnit
配置说明 全局安装phpunit代码 composer global require phpunit/phpunit 该代码会自动保存在 /User/你的用户名/.composer/vendor/ph ...
- Junit4使用详解一:测试失败的两种情况
Junit4最佳实践 1.把测试文件夹和代码文件夹分离,这两者的代码互不干扰,代码目录和测试目录是并列的关系 2.Java代码 3.创建单元测试代码文件 4.运行测试代码 5.查看测试结果 现在的情 ...
- 系统学习 Java IO (九)----缓冲流 BufferedInputStream/BufferedOutputStream
目录:系统学习 Java IO---- 目录,概览 BufferedInputStream BufferedInputStream 类为输入流提供缓冲. 缓冲可以加快IO的速度. BufferedIn ...
- 【通过ssh oracle11g安装】centos6静默安装oracle11g
转载链接:https://blog.csdn.net/u011391839/article/details/76566316 根据实际情况略作调整~ 博主参考了以上链接成功进行安装,列一下自己遇到的坑 ...
- swoole异步任务数据报表生成
<?php include 'vendor/autoload.php'; class server { private $serv; private $db; /** * [__construc ...
- java中方法的重载和覆盖
java中方法的重载和覆盖 先来了解一下这两个名词的含义. 重载: 在一个类当中才可以重载,方法名相同,参数个数不同或参数个数相同而参数类型不同. 覆盖: 又称重写,在派生类(子类)中重写基类(父类) ...
- putty秘钥转换成xhell支持的格式
使用XShell导入KEY的时候报“Failed to import the user key!”错误 这个错误表明导入的private key文件不是XShell所支持的,有三种可能: 将Publi ...
- JavaScript 之有趣的函数(函数声明、调用、预解析、作用域)
前言:“函数是对象,函数名是指针.”,函数名仅仅是指向函数的指针,与其他包含函数指针的变量没有什么区别,话句话说,一个函数可能有多个名字. -1.函数声明,function+函数名称.调用方法:函数名 ...
- 浅谈c++中的KMP
百度上一些关于KMP算法的一些基本介绍 所谓KMP,其实就是一种经过改进的模式串匹配算法(即在原串A中查找是否存在模式串B) 通常情况下,我们是这样匹配的 串A X Y Z X X Y Z X ...