​有多少小伙伴用着 JDK8 却写着 JDK6 的代码

2021-07-21 14:03 Java后端

有多少小伙伴在用着 JDK8 却写着 JDK6 的代码,松哥最近在连载 WebFlux,深感 JDK8 中的 Lambda、函数式接口,JDK9 中的 FlowAPI 的重要,因此一直想整篇文章和大家梳理下从 JDK8 开始 Java 的一些变化,刚好最近在网上看到这篇文章,就顺手和大家分享下。

JAVA 这几年的更新实在是太太太……快了,JAVA 8 都还没用多久,16 都已经发布了。自从 JAVA 8 发布了 Lambda 和 Stream 之后,JAVA 就像打了鸡血一样,半年一个版本的发布,生产队的驴也没这么勤快。

图片

导致我们现在完全跟不上 JAVA 发布的节奏,我司目前还停留在 JAVA 8,甚至部分老系统还在使用 JAVA 7,根本不能轻易的升级。

不过虽然暂时用不上最新版本的 JAVA,但了解每个新版本的主要特性还是很重要的,不然哪天真跟着升级了,那还不得一脸懵逼。
本文就带你快速了解 JAVA 9 - 16 的主要新特性,早学完早下班!

JAVA 9(2017年9月)

接口里可以添加私有接口

JAVA 8 对接口增加了默认方法的支持,在 JAVA 9 中对该功能又来了一次升级,现在可以在接口里定义私有方法,然后在默认方法里调用接口的私有方法。
这样一来,既可以重用私有方法里的代码,又可以不公开代码
public interface TestInterface {
    default void wrapMethod(){
        innerMethod();
    }
    private void innerMethod(){
        System.out.println("");
    }
}

匿名内部类也支持钻石(diamond)运算符

JAVA 5 就引入了泛型(generic),到了 JAVA 7 开始支持钻石(diamond)运算符:<>,可以自动推断泛型的类型:
List<Integer> numbers = new ArrayList<>();
但是这个自动推断类型的钻石运算符可不支持匿名内部类,在 JAVA 9 中也对匿名内部类做了支持:
List<Integer> numbers = new ArrayList<>() {
    ...
}

增强的 try-with-resources

JAVA 7 中增加了try-with-resources的支持,可以自动关闭资源:
try (BufferedReader bufferReader = new BufferedReader(...)) {
    return bufferReader.readLine();
}
但需要声明多个资源变量时,代码看着就有点恶心了,需要在 try 中写多个变量的创建过程:
try (BufferedReader bufferReader0 = new BufferedReader(...);
    BufferedReader bufferReader1 = new BufferedReader(...)) {
    return bufferReader0.readLine();
}
JAVA 9 中对这个功能进行了增强,可以引用 try 代码块之外的变量来自动关闭:
BufferedReader bufferReader0 = new BufferedReader(...);
BufferedReader bufferReader1 = new BufferedReader(...);
try (bufferReader0; bufferReader1) {
    System.out.println(br1.readLine() + br2.readLine());
}

JAVA 10(2018年3月)

局部变量的自动类型推断(var)

JAVA 10 带来了一个很有意思的语法 - var,它可以自动推断局部变量的类型,以后再也不用写类型了,也不用靠 lombok 的 var 注解增强了
var message = "Hello, Java 10";
不过这个只是语法糖,编译后变量还是有类型的,使用时还是考虑下可维护性的问题,不然写多了可就成 JavaScript 风格了

JAVA 11(2018年9月)

Lambda 中的自动类型推断(var)

JAVA 11 中对 Lambda 语法也支持了 var 这个自动类型推断的变量,通过 var 变量还可以增加额外的注解:
List<String> languages = Arrays.asList("Java""Groovy");
String language = sampleList.stream()
  .map((@Nonnull var x) -> x.toUpperCase())
  .collect(Collectors.joining(", "));

assertThat(language).isEqualTo("Java, Groovy");

javac + java 命令一把梭

以前编译一个 java 文件时,需要先 javac 编译为 class,然后再用 java 执行,现在可以一把梭了:
$ java HelloWorld.java
Hello Java 11!

Java Flight Recorder 登陆 OpenJDK

Java Flight Recorder 是个灰常好用的调试诊断工具,不过之前是在 Oracle JDK 中,也跟着 JDK 11 开源了,OpenJDK 这下也可以用这个功能,真香!

JAVA 12(2019年3月)

更简洁的 switch 语法

在之前的 JAVA 版本中,switch 语法还是比较啰嗦的,如果多个值走一个逻辑需要写多个 case
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
String typeOfDay = "";
switch (dayOfWeek) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        typeOfDay = "Working Day";
        break;
    case SATURDAY:
    case SUNDAY:
        typeOfDay = "Day Off";
}
到了 JAVA 12,这个事情就变得很简单了,几行搞定,而且!还支持返回值:
typeOfDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
    case SATURDAY, SUNDAY -> "Day Off";
};

instanceof + 类型强转一步到位

之前处理动态类型碰上要强转时,需要先 instanceof 判断一下,然后再强转为该类型处理:
Object obj = "Hello Java 12!";
if (obj instanceof String) {
    String s = (String) obj;
    int length = s.length();
}
现在 instanceof 支持直接类型转换了,不需要再来一次额外的强转:
Object obj = "Hello Java 12!";
if (obj instanceof String str) {
    int length = str.length();
}

JAVA 13(2019年9月)

switch 语法再增强

JAVA 12 中虽然增强了 swtich 语法,但并不能在 -> 之后写复杂的逻辑,JAVA 12 带来了 swtich更完美的体验,就像 lambda 一样,可以写逻辑,然后再返回:
typeOfDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
        // do sth...
        yield "Working Day";
    }
    case SATURDAY, SUNDAY -> "Day Off";
};

文本块(Text Block)的支持

你是否还在为大段带换行符的字符串报文所困扰,换行吧一堆换行符,不换行吧看着又难受:
String json = "{\"id\":\"1697301681936888\",\"nickname\":\"空无\",\"homepage\":\"https://juejin.cn/user/1697301681936888\"}";
JAVA 13 中帮你解决了这个恶心的问题,增加了文本块的支持,现在可以开心的换行拼字符串了,就像用模板一样:
String json = """
                {
                    "
id":"1697301681936888",
                    "
nickname":"空无",
                    "
homepage":"https://juejin.cn/user/1697301681936888"
                }
                """;

JAVA 14(2020年3月)

新增的 record 类型,干掉复杂的 POJO 类

一般我们创建一个 POJO 类,需要定义属性列表,构造函数,getter/setter,比较麻烦。JAVA 14 为我们带来了一个便捷的创建类的方式 - record
public record UserDTO(String id,String nickname,String homepage) { };

public static void main( String[] args ){
    UserDTO user = new UserDTO("1697301681936888","空无","https://juejin.cn/user/1697301681936888");
    System.out.println(user.id);
    System.out.println(user.nickname);
    System.out.println(user.id);
}
IDEA 也早已支持了这个功能,创建类的时候直接就可以选:

图片

不过这个只是一个语法糖,编译后还是一个 Class,和普通的 Class 区别不大

更直观的 NullPointerException 提示

NullPointerException 算是 JAVA 里最常见的一个异常了,但这玩意提示实在不友好,遇到一些长一点的链式表达式时,没办法分辨到底是哪个对象为空。
比如下面这个例子中,到底是 innerMap 为空呢,还是 effected 为空呢?
Map<String,Map<String,Boolean>> wrapMap = new HashMap<>();
wrapMap.put("innerMap",new HashMap<>());

boolean effected = wrapMap.get("innerMap").get("effected");

// StackTrace:
Exception in thread "main" java.lang.NullPointerException
    at org.example.App.main(App.java:50)
本文章转载自公众号:web_resource

首页 - Java 相关的更多文章: