前言

Java 平台自出现到目前为止,已经 20 多个年头了,这 20 多年间 Java 也一直作为最流行的程序设计语言之一,不断面临着其他新兴编程语言的挑战与冲击。Java 语言是一种静态强类型语言,这样的语言特性可以让 Java 编译器在编译阶段发现错误,这对于构建出一个稳定安全且健壮的应用来说,尤为重要。但是也因为这种特性,让 Java 开发似乎变得缺少灵活性,开发某些功能的应用时,代码量可能是其他语言的几倍。Java 开发的不足之处也体现越来越复杂的 JDK 上,越来越复杂的 JDK 让开发者完全理解的难度变的非常大。以至于开发者有时会重复实现一个 JDK 中已经提供了的功能。

为了跟上互联网应用编程发展的脚步, Java 从 9 版本开始调整了 JDK 发布的节奏,JDK 的每次更新都注重提高生产效率,提高 JVM 性能,推行模块化等,让开发者可以更多的专注于业务本身,而不是浪费过多的时间在语言特性上。 Java 语言的更新要在语言的严谨性和灵活性上找到一个平衡点,毕竟灵活性可以减少编码的复杂度,而严谨性是构建复杂且健壮应用的基石。

Java 7 语言特性

Java 重要的更新版本是在 Java 5 版本,这个版本中增加了如泛型、增强 for、自动装箱拆箱、枚举类型,可变参数、注解等一系列重要功能,但是随后的 Java 6 中并没有增加新的重要的语言特性。Java 5 的发布是在 2004 年,已经很久远了,网上关于 Java 的教程也大多是基于 Java 6 的,也因此我准备从 Java 7 开始介绍每个 Java 版本的新特性。

下面所有代码的运行演示都是基于 Java 7 ,所以你如果尝试下面的代码,需要安装并配置 Jdk 1.7 或者已上版本。

1. switch String

在 Java 7 之前,switch 语法中只支持整数类型以及这些整数类型的封装类进行判断,在 Java 7 中,支持了 string 字符串类型的判断,使用起来非常的简单,但是实用性是很高的。

1.1. switch String 基本用法

编写一个简单的 switch 判断字符串的测试类。

public class SwitchWithString {

    public static void main(String[] args) {
String gender = "男";
System.out.println(gender.hashCode());
switch (gender) {
case "男":
System.out.println("先生你好");
break;
case "女":
System.out.println("女士你好");
break;
default:
System.out.println("你好");
}
}
}

switch 判断字符串使用起来很简单,结果也显而易见会先输出 gender 变量的 hashCode,然后输出匹配结果“先生你好”。

30007
先生你好

在使用 switch string 时候,如果结合 Java 5 的枚举类,那么效果会更好,Java 7 之前使用枚举类要为每个值编数字代号,Java 7 之后可以直接定义字符串名称。

1.2. switch String 实现原理

但是这个支持只是编译器层面的支持, JVM 依旧是不支持的。在对字符串进行 switch 时,编译器会把字符串转换成整数类型再进行判断。为了验证上面说的只是编译器层面的支持,我们反编译(可以使用 Jad 反编译工具,也可以在 Idea 中双击编译生成的 class )生成的 class 文件,看到编译器把 switch string 转换成了字符串 hashCode 判断,为了防止 hashCode 冲突,又使用了 equals 再次判断。

public class SwitchWithString {
public SwitchWithString() {
} public static void main(String[] args) {
String gender = "男";
System.out.println(gender.hashCode());
byte var3 = -1;
switch(gender.hashCode()) {
case 22899:
if (gender.equals("女")) {
var3 = 1;
}
break;
case 30007:
if (gender.equals("男")) {
var3 = 0;
}
} switch(var3) {
case 0:
System.out.println("先生你好");
break;
case 1:
System.out.println("女士你好");
break;
default:
System.out.println("你好");
} }
}

2. try-with-resource

Java 不同于 C++,需要开发者自己管理每一块内存,大多时候 Java 虚拟机都可以很好的帮我们进行资源管理,但是也有时候需要手动释放一些资源,比如数据库连接、磁盘文件连接、网络连接等。换句话说,只要是资源数量有限的,都需要我们手动的进行释放。

2.1. try-catch-finally

在操作有限资源的时候,可能会出现各种异常,不管是读取阶段还是在最后关闭资源的过程中,都有可能出现问题,我们通常会使用下面的方式 try-catch-finally 保证资源的释放。

像下面这样。

/**
* 释放资源
*
* @author www.codingme.net
*/
public class TryCatachFinally { /**
* 异常处理
*
* @param args
*/
public static void main(String[] args) throws Exception {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("jdk-feature-7.iml");
} catch (FileNotFoundException e) {
throw e;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw e;
}
}
}
}
}

看看这恶心的代码结构,为了捕获异常,我们写了一个 catch,为了能保证释放资源,我们又写了 finally 进行资源释放,在资源释放时为了捕捉 close 时抛出的异常,我们又写了一个 try-catch。最后看着这复杂的代码,如果有人告诉你这段代码有 bug,那你一定不会相信。但是确实是这样,看起来严密的代码逻辑,当 try 中的代码逻辑和 close 方法同时产生异常的时候,try 中的异常信息会丢失。

可以看这里例子。

package net.codingme.feature.jdk7;

import java.io.IOException;

/**
* 释放资源
*
* @author www.codingme.net
*/
public class TryCatachFinallyThrow { /**
* 异常处理
*
* @param args
*/
public static void main(String[] args) throws Exception {
read();
} public static void read() throws Exception {
FileRead fileRead = null;
try {
fileRead = new FileRead();
fileRead.read();
} catch (Exception e) {
throw e;
} finally {
if (fileRead != null) {
try {
fileRead.close();
} catch (Exception e) {
throw e;
}
}
} }
} class FileRead { public void read() throws Exception {
throw new IOException("读取异常");
} public void close() throws Exception {
System.out.println("资源关闭");
throw new IOException("关闭异常");
}
}

很明显代码里 readclose 方法都会产生异常,但是运行程序发现只能收到 close 的异常信息。

资源关闭
Exception in thread "main" java.io.IOException: 关闭异常
at net.codingme.feature.jdk7.FileRead.close(TryCatachFinallyThrow.java:51)
at net.codingme.feature.jdk7.TryCatachFinallyThrow.read(TryCatachFinallyThrow.java:33)
at net.codingme.feature.jdk7.TryCatachFinallyThrow.main(TryCatachFinallyThrow.java:20)

异常信息丢失了,可怕的是你以为只是 close 时发生了异常而已。

2.2. try-autocloseable

上面的问题在 Java 7 中其实已经提供了新的解决方式,Java 7 中对 try 进行了增强,可以保证资源总能被正确释放 。使用增强 try 的前提是 try 中的类实现了 AutoCloseable 接口,在 Java 7 中大量的需要释放资源的操作其实都已经实现了此接口了。

实现了 AutoCloseable 的类,在增强 try中使用时,不用担心资源的关闭,在使用完毕会自动的调用 close方法,并且异常不会丢失

让我们编写的模拟资源操作的类实现 AutoCloseable 接口,然后时候增强 try 看看效果。

package net.codingme.feature.jdk7;

/**
* 自动关闭
*
* @author www.codingme.net
*/
public class AutoCloseResource {
public static void main(String[] args) throws Exception {
try (Mysql mysql = new Mysql();
OracleDatabase oracleDatabase = new OracleDatabase()) {
mysql.conn();
oracleDatabase.conn();
}
}
} class Mysql implements AutoCloseable { @Override
public void close() throws Exception {
System.out.println("mysql 已关闭");
} public void conn() {
System.out.println("mysql 已连接");
}
} class OracleDatabase implements AutoCloseable { @Override
public void close() throws Exception {
System.out.println("OracleDatabase 已关闭");
} public void conn() {
System.out.println("OracleDatabase 已连接");
}
}

测试类 Mysql 和 OracleDatabase 都是实现了 AutoCloseable,运行查看结果。

mysql 已连接
OracleDatabase 已连接
OracleDatabase 已关闭
mysql 已关闭

确认在发生异常时候异常信息不会丢失,写一个有异常的模拟测试类进行测试。

package net.codingme.feature.jdk7;

import java.io.IOException;

/**
* 释放资源
*
* @author www.codingme.net
*/
public class AutoCloseThrow { public static void main(String[] args) throws Exception {
try (FileReadAutoClose fileRead = new FileReadAutoClose()) {
fileRead.read();
}
}
} class FileReadAutoClose implements AutoCloseable { public void read() throws Exception {
System.out.println("资源读取");
throw new IOException("读取异常");
} @Override
public void close() throws Exception {
System.out.println("资源关闭");
throw new IOException("关闭异常");
}
}

运行查看异常信息。

资源读取
资源关闭
Exception in thread "main" java.io.IOException: 读取异常
at net.codingme.feature.jdk7.FileReadAutoClose.read(AutoCloseThrow.java:23)
at net.codingme.feature.jdk7.AutoCloseThrow.main(AutoCloseThrow.java:14)
Suppressed: java.io.IOException: 关闭异常
at net.codingme.feature.jdk7.FileReadAutoClose.close(AutoCloseThrow.java:29)
at net.codingme.feature.jdk7.AutoCloseThrow.main(AutoCloseThrow.java:15)

自动关闭,异常清晰,关闭异常存在于 Suppressed ,称为抑制异常,后续文章会详细介绍。

3. try-catch

在 Java 7 之前,一个 catch 只能捕获一个异常信息,当异常种类非常多的时候就很麻烦,但是在 Java 7 中,一个 catch 可以捕获多个异常信息,每个异常捕获之间使用 | 分割,

package net.codingme.feature.jdk7;

import java.io.IOException;

/**
* 多异常捕获
*/
public class TryCatchMany { public static void main(String[] args) {
try (TxtRead txtRead = new TxtRead()) {
txtRead.reader();
} catch (IOException | NoSuchFieldException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
} class TxtRead implements AutoCloseable { @Override
public void close() throws Exception {
System.out.println("资源释放");
} public void reader() throws IOException, NoSuchFieldException {
System.out.println("数据读取");
}
}

需要注意的是,一个 catch 捕获多个异常时,不能出现重复的异常类型,也不能出现一个异常类型是另一个类的子类的情况。

4. 二进制

Java 7 开始,可以直接指定不同的进制数字。

  1. 二进制指定数字值,只需要使用 0b 或者 OB 开头。
  2. 八进制指定数字值,使用 0 开头。
  3. 十六进制指定数字值,使用 0x 开头。
/**
* 二进制
*
* @author www.codingme.net
*/
public class Binary {
public static void main(String[] args) {
// 二进制
System.out.println("------2进制-----");
int a = 0b001;
int b = 0b010;
System.out.println(a);
System.out.println(b);
// 八进制
System.out.println("------8进制-----");
int a1 = 010;
int b1 = 020;
System.out.println(a1);
System.out.println(b1);
// 十六进制
System.out.println("------16进制-----");
int a2 = 0x10;
int b2 = 0x20;
System.out.println(a2);
System.out.println(b2);
}
}

输出结果。

------2进制-----
1
2
------8进制-----
8
16
------16进制-----
16
32

5. 数字下划线

Java 7 开始支持在数字定义时候使用下划线分割,增加了数字的可读性。

/**
* 数字下环线
*
* @author www.codingme.net
*/
public class NumberLine {
public static void main(String[] args) {
int a = 1_000;
int b = 1_0__0_0_0_____00;
System.out.println(a);
System.out.println(b);
}
}

得到结果。

1000
1000000

6. 结束语

虽然 Java 7 早在 2011 年就已经发布了,但是据我发现,使用到 Java 7 开始的新特性新语法的并不多,所以我的 JDK 新特性系列文章计划从 Java 7 开始,一直介绍到目前已经发布的 Java 13,以后 Java 新版本更新的同时,这个新特性系列文章也会持续更新。

此去山高水远,愿能一路坚持,愿你我一路同行。

<完>

个人网站:https://www.codingme.net

如果你喜欢这篇文章,可以关注公众号,一起成长。

关注公众号回复资源可以没有套路的获取全网最火的的 Java 核心知识整理&面试核心资料。

还看不懂同事代码?快来补一波 Java 7 语法特性的更多相关文章

  1. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

  2. 还看不懂同事的代码?Lambda 表达式、函数接口了解一下

    当前时间:2019年 11月 11日,距离 JDK 14 发布时间(2020年3月17日)还有多少天? // 距离JDK 14 发布还有多少天? LocalDate jdk14 = LocalDate ...

  3. 和低效 IO 说再见,回头补一波 Java 7 的 NIO.2 特性

    其实在这之前已经写过一篇关于 Java 7 的新特性文章了,那篇文章主要介绍了 Java 7 的资源自动关闭.Switch String 实现原理.异常捕获 try-catch.新的二进制书写方式等, ...

  4. Node.js(转) -- 临时来说还看不懂!

    转自:http://blog.jobbole.com/53736/ 本文由 伯乐在线 - Lellansin 翻译.未经许可,禁止转载!英文出处:toptal.欢迎加入翻译组. 介绍 JavaScri ...

  5. Hibernnate延迟加载策略(这么详细你还看不懂)

    好久没有认真写过博客了,今天就好好的写一篇吧!!!!!!!!! 当Hibernate 从数据库中加载某个对象(例如:Dept对象)时,如果同时自动加载所有的关联的某个对象(例如:Emp对象),而程序实 ...

  6. Java进阶知识点2:看不懂的代码 - 协变与逆变

    一.背景 要搞懂Java中的协办与逆变,不得不从继承说起,如果没有继承,协变与逆变也天然不存在了. 我们知道,在Java的世界中,存在继承机制.比如MochaCoffee类是Coffee类的派生类,那 ...

  7. 面试还搞不懂redis,快看看这40道面试题(含答案和思维导图)

    Redis 面试题 1.什么是 Redis?. 2.Redis 的数据类型? 3.使用 Redis 有哪些好处? 4.Redis 相比 Memcached 有哪些优势? 5.Memcache 与 Re ...

  8. 【转】面试还搞不懂redis,快看看这40道Redis面试题(含答案和思维导图)

    ———————————————— 版权声明:本文为CSDN博主「程序员追风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog. ...

  9. 花了三天整理,Spring Cloud微服务如何设计异常处理机制?还看不懂算我输

    前言 首先说一下为什么发这篇文章,是这样的.之前和粉丝聊天的时候有聊到在采用Spring Cloud进行微服务架构设计时,微服务之间调用时异常处理机制应该如何设计的问题.我们知道在进行微服务架构设计时 ...

随机推荐

  1. oracle SELECT子句中避免使用 ‘ * ‘

    当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*’ 是一个方便的方法. 不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所 ...

  2. HDU 1026 BSF+优先队列+记录路径、

    #include<iostream> #include<cmath> #include<cstring> #include<cstdio> #inclu ...

  3. Python--day24--继承

    A_son.__bases__查看继承的父类是哪些 A. object是所有类的祖宗,所有的类都默认继承了object类. python中可以多继承 继承与抽象,先抽象再继承: example:

  4. tf.variable_scope 参数

    最近在看TensorFlow的变量管理,发现很多代码中tf.variable_scope()参数的数量及意义还不太清楚,特此记录: def __init__(self, name_or_scope, ...

  5. 2018-2-13-WPF-DelegateCommand-出现Specified-cast-is-not-valid

    title author date CreateTime categories WPF DelegateCommand 出现Specified cast is not valid lindexi 20 ...

  6. 【u212】&&【t036】最大和

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和. [ ...

  7. P1018 灵灵排数字

    题目描述 今天灵灵收到了n张卡片,他需要给他们从小到大排序. 输入格式 输入的第一行包含一个整数 \(n(1 \le n \le 10^5)\) . 输入的第二行包含 \(n\) 个正整数,以空格间隔 ...

  8. printk函数 打印设备编号

    偶尔地, 当从一个驱动打印消息, 你会想打印与感兴趣的硬件相关联的设备号. 打印主次 编号不是特别难, 但是, 为一致性考虑, 内核提供了一些实用的宏定义( 在 <linux/kdev_t.h& ...

  9. yum安装gcc和gcc-c++

    本次总结参考 博客:http://blog.csdn.net/robertkun/article/details/8466700  ,非常 感谢他的博客,帮我解决了问题. 今天安装gcc-c++时出现 ...

  10. The Preliminary Contest for ICPC Asia Nanjing 2019ICPC南京网络赛

    B.super_log (欧拉降幂) •题意 定一个一个运算log*,迭代表达式为 给定一个a,b计算直到迭代结果>=b时,最小的x,输出对m取余后的值 •思路 $log*_{a}(1)=1+l ...