java7 diamond_跟上 Java7:你忽略了的新特性

7829be1b962ebf4ea391390b1324928b.png

前言

Java7,代号「海豚(Dolphin)」,是 Java 历史上一次非常重大的版本更新,同时也是我入门学习 Java 所用的版本。本篇主要介绍几个很实用的 Java7 特性,文中若有用词不当或专业术语不准的现象,望见谅!

Java7 新特性:

1.二进制形式的字面值表示

2.在数值类型的字面值中使用下划线分隔符联接

3.创建泛型实例时自动类型推断

4.switch-case 语句支持字符串类型

5.新增 try-with-resources 语句

6.单个 catch 子句同时捕获多种异常类型

7.引入 java.util.Objects 工具类

二进制形式的字面值表示

由于继承 C 语言,Java 代码在传统上迫使程序员只能使用十进制,八进制或十六进制来表示数 (numbers)。Java SE 7 中,整数类型(byte、short、int 以及 long) 也可以使用二进制数系来表示。要指定一个二进制字面量,可以给二进制数字添加前缀 0b 或者 0B。

1

2

3

4

5

6

7

8

9

10

11

12

13// 一个 8 位的'byte'值:

byte aByte = (byte) 0b00100001;

// 一个 16 位的'short'值:

short aShort = (short) 0b1010000101000101;

// 几个 32 位的'int'值:[B 可以是大写或者小写]

int anInt1 = 0b10100001010001011010000101000101;

int anInt2 = 0b101;

int anInt3 = 0B101;

// 一个 64 位的'long'值. 注意 "L" 后缀:

long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;

支持的数字字面量表示:

十进制:默认的

八进制:整数之前加数字 0 来表示

十六进制:整数之前加 “0x” 或“0X”

二进制(新加的):整数之前加 “0b” 或“0B”

在数值类型的字面值中使用下划线分隔符联接

如果 Java 源代码中有一个很长的数值字面量,开发人员在阅读这段代码时需要很费力地去分辨数字的位数,以知道其所代表的数值大小。在现实生活中,当遇到很长的数字的时候,我们采取的是分段分隔的方式。比如数字 500000,我们通常会写成 500,000,即每三位数字用逗号分隔。利用这种方式就可以很快知道数值的大小。这种做法的理念被加入到了 Java7 中,不过用的不是逗号,而是下划线“_”。

1

2

3

4

5

6// 输出 56.34

System.out.println(5_6.3_4);

// 输出 8931

System.out.println(89_3___1);

// 输出 1500000

System.out.println(1_500_000);

注意:下划线只能出现在数字中间,前后必须是数字。所以“_100”、“0b_101“是不合法的,无法通过编译。

创建泛型实例时自动类型推断

只要编译器从上下文中能够推断出类型参数,你就可以使用一个空的类型参数集合 (<>) 代替调用一个泛型类的构造器所需要的类型参数。这对尖括号通常叫做 diamond。

1

2

3

4

5// 举个例子, 考虑下面的变量声明:

Map> myMap = new HashMap>();

// 在 Java SE 7 中, 你可以使用一个空的类型参数集合 (<>) 代替构造器的参数化类型:

Map> myMap = new HashMap<>();

注意:想要在泛型类初始化期间利用自动类型推断,你必须要指定 diamond。这个 <> 被叫做 diamond(钻石)运算符,Java 7 后这个运算符从引用的声明中推断类型。

switch-case 语句支持字符串类型

switch 语句可以使用原始类型或枚举类型。Java 引入了另一种类型,我们可以在 switch 语句中使用:字符串类型。

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

30String input = "Monday";

String output;

switch (input) {

case "Monday":

output = "星期一";

break;

case "Tuesday":

output = "星期二";

break;

case "Wednesday":

output = "星期三";

break;

case "Thursday":

output = "星期四";

break;

case "Friday":

output = "星期五";

break;

case "Saturday":

output = "星期六";

break;

case "Sunday":

output = "星期日";

break;

default:

throw new IllegalArgumentException("无效的输入参数:" + input);

}

// 输出: 星期一

System.out.println(output);

新增 try-with-resources 语句

Java 中某些资源是需要手动关闭的,如 InputStream,Writes,Sockets,Sqlclasses 等。这个新的语言特性允许 try 语句本身申请更多的资源,这些资源作用于 try 代码块,并自动关闭。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23// 传统的资源关闭方式[为了确保外部资源一定要被关闭, 通常关闭代码被写入 finally 代码块中, 当然我们还必须注意到关闭资源时可能抛出的异常]

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(new File("test"));

System.out.println(inputStream.read());

} catch (IOException e) {

throw new RuntimeException(e.getMessage(), e);

} finally {

if (inputStream != null) {

try {

inputStream.close();

} catch (IOException e) {

throw new RuntimeException(e.getMessage(), e);

}

}

}

// try-with-resource 语法

try (FileInputStream inputStreamForResource = new FileInputStream(new File("test"))) {

System.out.println(inputStreamForResource.read());

} catch (IOException e) {

throw new RuntimeException(e.getMessage(), e);

}

那什么是 try-with-resource 呢?简而言之,当一个外部资源的句柄对象(比如 FileInputStream 对象)实现了 AutoCloseable 接口,将外部资源的句柄对象的创建放在 try 关键字后面的括号中,当这个 try-catch 代码块执行完毕后,Java 会确保外部资源的 close 方法被调用。

单个 catch 子句同时捕获多种异常类型

在 Java7 中,catch 代码块得到了升级,用以在单个 catch 块中处理多个异常。如果你要捕获多个异常并且它们包含相似的代码,使用这一特性将会减少代码重复度。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17// Java 7 之前的版本:

try {

// 具体的处理代码

} catch (InstantiationException e) {

// 捕获异常的处理方式

} catch (IllegalAccessException e) {

// 捕获异常的处理方式

} catch (ClassNotFoundException e) {

// 捕获异常的处理方式

}

// 在 Java 7 中,我们可以用一个 catch 块捕获所有这些异常:

try {

// 具体的处理代码

} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {

// 捕获异常的处理方式

}

引入 java.util.Objects 工具类

引入 java.util.Objects 工具类,用于封装一些平时使用频度很高或容易出错的操作。

(1)Objects.equals(Object a, Object b):有别于 Object.equals(Object a, Object b),这个方法可以避免空指针异常。

1

2

3public static boolean equals(Object a, Object b) {

return (a == b) || (a != null && a.equals(b));

}

(2)Objects.deepEquals(Object a, Object b):Object.equals(Object a, Object b) 用于比较两个对象的引用是否相同,而 deepEquals() 却扩展成了可以支持数组。

1

2

3

4

5

6

7

8public static boolean deepEquals(Object a, Object b){

if (a == b)

return true;

else if (a == null || b == null)

return false;

else

return Arrays.deepEquals0(a, b);

}

(3)Objects.hashCode(Object o):和 Object.hashCode(Object o) 类似,只是在对象为 null 时返回的散列值为 0 而已。

1

2

3public static int hashCode(Object o){

return o != null ? o.hashCode() : 0;

}

(4)Objects.hash(Object… values):生成对象的散列值,包括数组。

1

2

3public static int hash(Object... values){

return Arrays.hashCode(values);

}

(5)Objects.toString(Object o):归根结底,其内部最终调用了对象的 toString() 方法。只是额外多了空指针判断而已。

1

2

3

4

5

6

7public static String toString(Object o) {

return String.valueOf(o);

}

public static String valueOf(Object obj) {

return (obj == null) ? "null" : obj.toString();

}

(6)Objects.compare(T a, T b, Comparator< ? super T> c):用于比较两个对象。

1

2

3public static int compare(T a, T b, Comparator super T> c){

return (a == b) ? 0 : c.compare(a, b);

}

(7)Objects.requireNonNull(T obj):在对象为空指针时,抛出特定 message 的空指针异常。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17public static T requireNonNull(T obj) {

if (obj == null)

throw new NullPointerException();

return obj;

}

public static T requireNonNull(T obj, String message) {

if (obj == null)

throw new NullPointerException(message);

return obj;

}

public static T requireNonNull(T obj, Supplier messageSupplier) {

if (obj == null)

throw new NullPointerException(messageSupplier.get());

return obj;

}

(8)Objects.isNull(Object obj) / Objects.nonNull(Object obj):这两个方法用于判断对象为 null 和对象不为 null。通常情况下,我们不会直接使用这两个方法,而是使用比较操作符 == 和 !=。这两个方法主要用在 jdk8 开始支持的流计算里面。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17public static T requireNonNull(T obj) {

if (obj == null)

throw new NullPointerException();

return obj;

}

public static T requireNonNull(T obj, String message) {

if (obj == null)

throw new NullPointerException(message);

return obj;

}

public static T requireNonNull(T obj, Supplier messageSupplier) {

if (obj == null)

throw new NullPointerException(messageSupplier.get());

return obj;

}

参考博文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值