Java7新特性

Java7的新特性

新的invokedynamic字节码指令

JVM本身对动态语言的支持:新的invokedynamic字节码指令(JSR-292),与多语言虚拟机(Multi Language Virtual Machine)原型

Java语言的动态性-invokedynamic

新的 File I/O 程序库

新的文件 I/O 程序库 (JSR 203 定义) 增加多重文件的支持、文件原始数据和符号链接。新的包为:java.nio.filejava.nio.file.attributejava.nio.file.spi

Timsort 混合排序算法

使用 Timsort 来为集合与数组排序,取代归并排序

java sort排序源码分析(TimSort排序)

增强对新网络通信协议的支持

增强了对新网络通信协议(包括 SCTPSockets Direct Protocol )的标准库级别的支持

一些语言方面的小改变

在switch中使用字符串类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static void main(String[] args) {
String s = "test";
switch (s) {
case "test":
System.out.println("test");
case "test1":
System.out.println("test1");
break;
default:
System.out.println("break");
break;
}
}
}

类型推论

针对泛型实例的创建而改善的类型推论,被称为钻石操作符<>

1
List<String> list = new ArrayList<>();

捕获多个异常

允许在一个 catch 中捕捉多个类型的异常,并使用改进的类型检查重新抛出异常。

1
2
3
4
5
6
7
public void handle() {
try {
throw new IOException();
} catch (IOException | RuntimeException e) {
e.printStackTrace();
}
}

Suppress异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 记录被抑制的异常,不被淹没。
*
* @since 1.7
*/
public class SuppressException {
public static void main(String[] args) throws Exception {
Exception e_ = null;

try {
System.out.println("执行顺序:1 -- try块打印");
throw new Exception("try块异常 -- try块抛出异常");
} catch (Exception e) {
System.out.println("执行顺序:2 -- catch块打印");

e.printStackTrace(System.out);

// 将catch块中的异常传递给finally。
e_ = e;

// 抛出捕捉到的try块异常
throw e;
} finally {
System.out.println("执行顺序:3 -- finally块打印");

Exception e = new Exception("finally块异常 -- finally块抛出异常并向上传递, catch块异常不再传递, 即被忽略");
if (e_ != null) {
/**
* 向抛出的异常中添加suppress异常。
* @since 1.7
*/
e.addSuppressed(e_);
}
throw e;
}
}
}

try-with-resources 自动资源管理

1
2
3
4
5
public enum SwitchConstant {
OPEN_CATCH,
OPEN_FINALLY,
OPEN_ALL;
}

Java SE 7 之前

使用 try-catch-finally 异常处理机制,资源声明在 try-catch-finally 语句外部,使用的资源需要被明确地关闭。

无法检索被抑制的异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Java7Before {

public static void main(String[] args) throws Exception {
// method(null);
// method(SwitchConstant.OPEN_CATCH.name());
// method(SwitchConstant.OPEN_FINALLY.name());
// method(SwitchConstant.OPEN_ALL.name());
}

public static void method(String openStr) throws IOException {
BufferedOutputStream bos = null;
BufferedOutputStream bos2 = null;
try {
bos = new BufferedOutputStream(new FileOutputStream("EmptyFile.txt", true));
bos2 = new BufferedOutputStream(new FileOutputStream("EmptyFile.txt", true));

System.out.println("执行顺序:1 -- try块打印");
throw new IOException("try块异常 -- try块抛出异常");
} catch (IOException e) {
System.out.println("执行顺序:2 -- catch块打印");

e.printStackTrace(System.out);

boolean condition = !StringUtils.isEmpty(openStr) && (openStr.equals(SwitchConstant.OPEN_ALL.name()) || openStr.equals(SwitchConstant.OPEN_CATCH.name()));
if (condition) {
throw new IOException("catch块异常 -- catch块抛出新异常并向上传递; 捕捉到的try块异常不再传递, 即被忽略");
}
} finally {
System.out.println("执行顺序:3 -- finally块打印");

try {
if (bos != null) {
bos.close();
}
if (bos2 != null) {
bos2.close();
}
} catch (IOException e) {
e.printStackTrace();
}

boolean condition = !StringUtils.isEmpty(openStr) && (openStr.equals(SwitchConstant.OPEN_ALL.name()) || openStr.equals(SwitchConstant.OPEN_FINALLY.name()));
if (condition) {
throw new IOException("finally块异常 -- finally块抛出异常并向上传递, catch块异常不再传递, 即被忽略");
}
}
}
}

Java SE 7 以后

新的 try-with-resources 异常处理机制,资源的声明在 resources 块,且只能在 try 语句块内使用声明的资源

当程序运行离开 try 语句块时,声明的资源会按照创建顺序的逆序自动关闭。

可以调用 public final Java.lang.Throwable[] getSuppressed() 函数来检索被抑制的异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class Java7After {

public static void main(String[] args) throws Exception {
// method(null);
// method(SwitchConstant.OPEN_CATCH.name());
// method(SwitchConstant.OPEN_FINALLY.name());
// method(SwitchConstant.OPEN_ALL.name());
}

public static void method(String openStr) throws Exception {
try (
/**
* 我称之为'resources块'
* 在此处声明一个或多个try语句的资源。
* 所有实现 java.lang.AutoCloseable 接口的类都可以在 try-with-resources 结构中使用。
* 当程序运行离开try语句块时,声明的资源会按照创建顺序的逆序自动关闭。
* 如下两个资源:bos先关闭,bis后关闭。
*/
CustomAutoClosable customAutoClosable = new CustomAutoClosable();
CustomAutoClosable customAutoClosable2 = new CustomAutoClosable()
) {
System.out.println("执行顺序:1 -- try块打印");
throw new IOException("try块异常 -- try块抛出异常, resources块异常附加到为了传递此异常而被抑制的异常(Throwable.addSuppressed)");
} catch (IOException e) {
System.out.println("执行顺序:2 -- catch块打印");

// Console中文本流的顺序问题
e.printStackTrace(System.out);

int num = e.getSuppressed().length;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("执行顺序:3 -- catch块捕捉到异常:\n");
stringBuilder.append("\t\t\t\t\t" + "try块异常:\n");
stringBuilder.append("\t\t\t\t\t\t" + e.getMessage() + "\n");
stringBuilder.append("\t\t\t\t\t" + "try块异常中被抑制的" + num + "个resources块异常:");
for (Throwable throwable : e.getSuppressed()) {
stringBuilder.append("\n\t\t\t\t\t\t");
stringBuilder.append(throwable.getMessage());
}
System.out.println(stringBuilder);

boolean condition = !StringUtils.isEmpty(openStr) && (openStr.equals(SwitchConstant.OPEN_ALL.name()) || openStr.equals(SwitchConstant.OPEN_CATCH.name()));
if (condition) {
throw new IOException("catch块异常 -- catch块抛出新异常并向上传递; 捕捉到的try块异常不再传递, 即被忽略");
}
} finally {
System.out.println("执行顺序:4 -- finally块打印");

boolean condition = !StringUtils.isEmpty(openStr) && (openStr.equals(SwitchConstant.OPEN_ALL.name()) || openStr.equals(SwitchConstant.OPEN_FINALLY.name()));
if (condition) {
throw new IOException("finally块异常 -- finally块抛出异常并向上传递, catch块异常不再传递, 即被忽略");
}
}
}

/**
* 自定义CustomAutoClosable,实现AutoCloseable接口,观察close方法的执行时机。
*/
static class CustomAutoClosable implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("\t" + "资源关闭打印");
throw new Exception("资源关闭异常");
}
}
}

允许在数值字面值中加入下划线

1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
int a = 1_2_8;
System.out.println(a);
}
}

二进制整数字面值

什么是Java的字面值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Test {
public static void main(String[] args) {
// 二进制字面值以0b或0B开头,不区分大小写。

/**
* -1的二进制表示
* 原码: 1000_0001
* 反码: 1111_1110
* 补码: 1111_1111
*/
byte complement = (byte) 0B1111_1111;
System.out.println(complement);

// 一个8位的byte值:
byte b = (byte) 0b1000_0000;
System.out.println(Byte.MIN_VALUE);
System.out.println(b);
// 一个16位的short值:
short s = (short) 0b1000_0000_0000_0000;
System.out.println(Short.MIN_VALUE);
System.out.println(s);
// 一个32位的int值:
int i = 0b1000_0000_0000_0000_0000_0000_0000_0000;
System.out.println(Integer.MIN_VALUE);
System.out.println(i);
// 一个64位的long值(注意末尾的后缀“L”)
long l = 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L;
System.out.println(l);
}
}