Java1.7新特性
1.switch语句支持字符串变量
public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
String typeOfDay;
switch (dayOfWeekArg) {
case "Monday":
typeOfDay = "Start of work week";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
typeOfDay = "Midweek";
break;
case "Friday":
typeOfDay = "End of work week";
break;
case "Saturday":
case "Sunday":
typeOfDay = "Weekend";
break;
default:
throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
return typeOfDay;
}
switch 语句比较表达式中的String对象和每个case标签关联的表达式,就好像它是在使用String.equals方法一样;因此,switch语句中 String对象的比较是大小写敏感的。相比于链式的if-then-else语句,Java编译器通常会从使用String对象的switch语句中生成更高效的字节码。
2.泛型实例化类型自动推断
以下两个语句等价:
ArrayList<String> al1 = new ArrayList<String>(); // Old
ArrayList<String> al2 = new ArrayList<>(); // New
3. 新的整数字面表达方式 - "0b"前缀和"_"连数符
a. 表示二进制字面值的前缀0b。
比如以下三个变量的值相同:
byte b1 = 0b00100001; // New
byte b2 = 0x21; // Old
byte b3 = 33; // Old
b. 字面常量数字的下划线。用下划线连接整数提升其可读性,自身无含义,不可用在数字的起始和末尾。
Java编码语言对给数值型的字面值加下划线有严格的规定。如上所述,你只能在数字之间用下划线。你不能用把一个数字用下划线开头,或者已下划线结尾。这里有一些其它的不能在数值型字面值上用下划线的地方:
- 在数字的开始或结尾
- 对浮点型数字的小数点附件
- F或L下标的前面
- 该数值型字面值是字符串类型的时候
float pi1 = 3_.1415F; // 无效的; 不能在小数点之前有下划线
float pi2 = 3._1415F; // 无效的; 不能在小数点之后有下划线
long socialSecurityNumber1=999_99_9999_L;//无效的,不能在L下标之前加下划线
int a1 = _52; // 这是一个下划线开头的标识符,不是个数字
int a2 = 5_2; // 有效
int a3 = 52_; // 无效的,不能以下划线结尾
int a4 = 5_______2; // 有效的
int a5 = 0_x52; // 无效,不能在0x之间有下划线
int a6 = 0x_52; // 无效的,不能在数字开头有下划线
int a7 = 0x5_2; // 有效的 (16进制数字)
int a8 = 0x52_; // 无效的,不能以下划线结尾
int a9 = 0_52; // 有效的(8进制数)
int a10 = 05_2; // 有效的(8进制数)
int a11 = 052_; // 无效的,不能以下划线结尾
4.在单个catch代码块中捕获多个异常,以及用升级版的类型检查重新抛出异常
在Java 7中,catch代码块得到了升级,用以在单个catch块中处理多个异常。如果你要捕获多个异常并且它们包含相似的代码,使用这一特性将会减少代码重复度。下面用一个例子来理解。
Java 7之前的版本:
catch (IOException ex) {
logger.error(ex);
throw new MyException(ex.getMessage());
catch (SQLException ex) {
logger.error(ex);
throw new MyException(ex.getMessage());
}catch (Exception ex) {
logger.error(ex);
throw new MyException(ex.getMessage());
}
在Java 7中,我们可以用一个catch块捕获所有这些异常:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
如果用一个catch块处理多个异常,可以用管道符(|)将它们分开,在这种情况下异常参数变量(ex)是定义为final的,所以不能被修改。这一特性将生成更少的字节码并减少代码冗余。
另一个升级是编译器对重新抛出异常(rethrown exceptions)的处理。这一特性允许在一个方法声明的throws从句中指定更多特定的异常类型。
与以前版本相比,Java SE 7 的编译器能够对再次抛出的异常(rethrown exception)做出更精确的分析。这使得你可以在一个方法声明的throws从句中指定更具体的异常类型。
我们先来看下面的一个例子:
static class FirstException extends Exception { }
static class SecondException extends Exception { } public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
这个例子中的try语句块可能会抛出FirstException或者SecondException类型的异常。设想一下,你想在rethrowException方法声明的throws从句中指定这些异常类型。在Java SE 7之前的版本,你无法做到。因为在catch子句中的异常参数e是java.lang.Exception类型的,catch子句对外抛出异常参数e,你只能在rethrowException方法声明的throws从句中指定抛出的异常类型为java.lang.Exception (或其父类java.lang.Throwable)。
不过,在Java SE 7中,你可以在rethrowException方法声明的throws从句中指定抛出的异常类型为FirstException和SecondException。Java SE 7的编译器能够判定这个被throw语句抛出的异常参数e肯定是来自于try子句,而try子句只会抛出FirstException或SecondException类型的异常。尽管catch子句的异常参数e是java.lang.Exception类型,但是编译器可以判断出它是FirstException或SecondException类型的一个实例:
public class Java7MultipleExceptions { public static void main(String[] args) {
try{
rethrow("abc");
}catch(FirstException | SecondException | ThirdException e){
//以下赋值将会在编译期抛出异常,因为e是final型的
//e = new Exception();
System.out.println(e.getMessage());
}
} static void rethrow(String s) throws FirstException, SecondException, ThirdException {
try {
if (s.equals("First"))
throw new FirstException("First");
else if (s.equals("Second"))
throw new SecondException("Second");
else
throw new ThirdException("Third");
} catch (Exception e) {
//下面的赋值没有启用重新抛出异常的类型检查功能,这是Java 7的新特性
// e=new ThirdException();
throw e;
}
} static class FirstException extends Exception { public FirstException(String msg) {
super(msg);
}
} static class SecondException extends Exception { public SecondException(String msg) {
super(msg);
}
} static class ThirdException extends Exception { public ThirdException(String msg) {
super(msg);
}
} }
不过,如果catch捕获的异常变量在catch子句中被重新赋值,那么异常类型检查的分析将不会启用,因此在这种情况下,你不得不在方法声明的throws从句中指定异常类型为java.lang.Exception。
更具体地说,从Java SE 7开始,当你在单个catch子句中声明一种或多种类型的异常,并且重新抛出这些被捕获的异常时,需符合下列条件,编译器才会对再次抛出的异常进行类型验证:
- try子句会抛出该异常。
- 在此之前,没有其他的catch子句捕获该异常。
- 该异常类型是catch子句捕获的多个异常中的一个异常类型的父类或子类。
5.try-with-resources语句
try-with-resources语句是一个声明一个或多个资源的try语句。一个资源作为一个对象,必须在程序结束之后关闭。try-with-resources语句确保在语句的最后每个资源都被关闭,任何实现了Java.lang.AutoCloseable和java.io.Closeable的对象都可以使用try-with-resource来实现异常处理和关闭资源。
下面通过对比来体会这个新特性。
JDK1.7之前:
/**
* JDK1.7之前我们必须在finally块中手动关闭资源,否则会导致资源的泄露
* @author Liao
*
*/
public class PreJDK7 { public static String readFirstLingFromFile(String path) throws IOException {
BufferedReader br = null; try {
br = new BufferedReader(new FileReader(path));
return br.readLine();
} catch (IOException e) {
e.printStackTrace();
} finally {//必须在这里关闭资源
if (br != null)
br.close();
}
return null;
}
}
JDK1.7及以后版本
/**
* JDK1.7之后就可以使用try-with-resources,不需要
* 我们在finally块中手动关闭资源
* @author Liao
*/
public class AboveJDK7 { static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
}
通过上面的对比,try-with-resources的优点
代码精炼,在JDK1.7之前都有finally块(这时可能会有一个问题,1.7后的finally将何去何从,还有用处吗?当然有用了,try-with-resources只是帮助我们避免了资源关闭的重复工作,但它并没有代替finally的作用啊,所以1.7后finally仍然是用来处理一定会被执行的代码块,不过这个功能使用场景不是很大。),如果使用一些扩建可能会将finally块交由框架处理,如spring。JDK及以后的版本只要资源类实现了AutoCloseable或Closeable程序在执行完try块后会自动close所使用的资源无论br.readLine()是否抛出异常,我估计针对JDK1.7像Spring这些框架也会做出一些比较大的调整。
代码更完全。在出现资源泄漏的程序中,很多情况是开发人员没有或者开发人员没有正确的关闭资源所导致的。JDK1.7之后采用try-with-resources的方式,则可以将资源关闭这种与业务实现没有很大直接关系的工作交给JVM完成,省去了部分开发中可能出现的代码风险。
异常抛出顺序
在JDK1.7之前如果rd.readLine()与rd.close()都抛出异常则只会抛出finally块中的异常,不会抛出rd.readLine()中的异常,这样经常会导致得到的异常信息不是调用程序想要得到的。
在JDK1.7及以后采用了try-with-resource机制,如果在try-with-resource声明中抛出异常(如文件无法打开或无法关闭)的同时rd.readLine()也抛出异常,则只会抛出rd.readLine()的异常。
try-with-resource可以声明多个资源(声明语句之间分号分割,最后一个可忽略分号)。下面的例子是在一个ZIP文件中检索文件名并将检索后的文件存入一个txt文件中。
JDK1.7及以上版本:
public class AboveJDK7_2 { public static void writeToFileZipFileContents(String zipFileName,String outputFileName) throws java.io.IOException { java.nio.charset.Charset charset = java.nio.charset.Charset.forName("US-ASCII"); java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName); //打开zip文件,创建输出流
try (
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {//遍历文件写入txt
for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) { String newLine = System.getProperty("line.separator"); String zipEntryName = ((java.util.zip.ZipEntry) entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
}
注:上面的例子,无论正常执行还是有异常抛出,zf和write都会被执行close()方法,不过需要注意的是在JVM里调用的顺序是与生命的顺序相反。在JVM中调用的顺讯为:
writer.close();
zf.close();
所以在使用时一定要注意资源关闭的顺序。
转自:http://www.jianshu.com/p/5ae0cb34622e
Java1.7新特性的更多相关文章
- java1.8新特性之stream流式算法
在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: List& ...
- Stream:java1.8新特性
原 Stream:java1.8新特性 2017年08月01日 18:15:43 kekeair-zhang 阅读数:392 标签: streamjava1-8新特性 更多 个人分类: 日记 版权声明 ...
- java1.8新特性(一)
一直在更新java 版本,原来也没有关注java版本的变化 引入的一些新的api 引起注意的还是 关于一些并发包的使用,那时候才对每个版本的特性 去了解了一下,虽然 不一定都用上了,但是不管学习什 ...
- java1.7新特性:try-with-resources
转载:https://blog.csdn.net/fanxiaobin577328725/article/details/53067163 首先看代码: import org.junit.Test; ...
- Java1.8新特性——接口改动和Lambda表达式
Java1.8新特性——接口改动和Lambda表达式 摘要:本文主要学习了Java1.8的新特性中有关接口和Lambda表达式的部分. 部分内容来自以下博客: https://www.cnblogs. ...
- java1.8新特性整理(全)
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yitian_66/article/deta ...
- Java1.8新特性 - Stream流式算法
一. 流式处理简介 在我接触到java8流式数据处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包 ...
- java1.8新特性
转自:http://www.oschina.NET/translate/everything-about-Java-8 建议去看原文,此处转载只是为了记录. 这篇文章是对Java8中即将到来的改进做一 ...
- java1.8新特性(三 关于 ::的用法)
java1.8 推出了一种::的语法 用法 身边 基本没人用1.8的新API 目前 我也是只处于学习 运用 阶段 有点 知其然不知其所以然 通过后面的学习,及时查漏补缺 一个类中 有 静态方法 ,非静 ...
随机推荐
- react 中文文档案例四 (登陆登出按钮)
import React from 'react'; import ReactDOM from 'react-dom'; class LoginControl extends React.Compon ...
- ubuntu下vnstat监控网卡流量
vnstat使用 vnstat 是另一个可以用来监视带宽使用量的程序.它比ipac-ng更简单易用. vnstat的一个优点是它不是一个运行的守护程序,所以它几乎不占用内存.它由 cron 任务创建, ...
- P4173 残缺的字符串(FFT)
[Luogu4173] 题解 \(1.\)定义匹配函数 \(2.\)定义完全匹配函数 \(3.\)快速计算每一位的完全匹配函数值 #include<cstdio> #include< ...
- Oracle 树形SQL语句,SYS_CONNECT_BY_PATH 函数
转一个SYS_CONNECT_BY_PATH 函数的例子.推断原表应该是这样: Child Parent ------------------------ ...
- Jenkins自动化CI CD流水线之2--用户权限管理
一. 背景 针对开发.运维.测试针对不同角色进行不同权限划分, 基于插件: Role-based Authorization Strategy来实现. 一. 安装 安装该插件: 系统管理->管理 ...
- web安全之文件上传漏洞攻击与防范方法
一. 文件上传漏洞与WebShell的关系 文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行.这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等.这种攻击方式是最为直接和有效 ...
- 创建有关hbase数据库的项目时所遇到的问题
1.在以前使用其他数据库时,经常会使用id自增来做主键,但是hbase数据库中不知道怎么来设置自增主键,所以我打算不要id自增主键.然后删除原来的表,重新创建表. 删除表语句: 用drop命令可以删除 ...
- c++ 多线程 0
1.1 何谓并发 最简单和最基本的并发,是指两个或更多独立的活动同时发生. (注意区别于计算机中的并发情况!!!!!!!!!!见下面) 1.1.1 计算机系统中的并发:是指在单个系统里同时执行多个独 ...
- (转)IBM AIX系统硬件信息查看命令(shell脚本)
IBM AIX系统硬件信息查看命令(shell脚本) 原文:http://blog.itpub.net/22085031/viewspace-1054015/ 查看IBM AIX系统的主机型号.序列号 ...
- Mysql数据库常用操作整理
0.说明 MySQL数据库是一个十分轻便的数据库管理系统,相比大型的数据库管理系统如Oracle,MySQL更拥有轻便.灵活.开发速度快的特色,更适用于中小型数据的存储与架构,被数以万计的网站采用.从 ...