Z次元
文章 笔记 日志
专题
专栏分类 文章归档
友链
友情链接 朋友圈
交流
留言 关于我
头像
系列文章
-
-
-
-
JDK新版特性(11-17)
系列文章
知识积累
最后更新:2025/2/15|创建时间:2025/1/30

文章主要介绍了JDK11-17新版本的主要特性

JDK12

升级的switch语句

在jdk12之前的switch语句中,如果没有写break,则会出现case穿透现象,下面是对case穿透的一个应用,根据输入的月份打印相应的季节。

int month = 3;
switch (month) {
    case 3:
    case 4:
    case 5:
        System.out.println("spring");
    break;
    case 6:
    case 7:
    case 8:
        System.out.println("summer");
    break;
    case 9:
    case 10:
    case 11:
        System.out.println("autumn");
    break;
    case 12:
    case 1:
    case 2:
        System.out.println("winter");
    break;
    default:
        System.out.println("wrong");
    break;
}

在jdk12之后我们可以省略全部的break和部分case,这样使用

    int month = 3;
    switch (month) {
        case 3,4,5 -> System.out.println("spring");
        case 6,7,8 -> System.out.println("summer");
        case 9,10,11 -> System.out.println("autumn");
        case 12, 1,2 -> System.out.println("winter");
        default -> System.out.println("wrong");
    }

这个是预览功能,如果需要编译和运行的话需要使用下面命令,预览功能在2个版本之后会成为正式版,即如果你使用的是jdk14以上的版本,正常的编译和运行即可。否则需要使用预览功能来编译和运行

编译:
    javac --enable-preview -source 12 Test.java

运行:
    java --enable-preview Test

JDK13

升级的switch语句

jdk13中对switch语句又进行了升级,可以switch的获取返回值

示例:

   int month = 3;
   String result = switch (month) {
        case 3,4,5 -> "spring";
        case 6,7,8 -> "summer";
        case 9,10,11 -> "autumn";
        case 12, 1,2 -> "winter";
        default -> "wrong";
    };

    System.out.println(result);

对于jdk15之后的版本可以直接编译和运行,否则需要使用下面命令执行该预览功能

编译:
    javac --enable-preview -source 13 Test.java

运行:
    java --enable-preview Test

文本块的变化

在jdk13之前的版本中如果输入的字符串中有换行的话,需要添加换行符

String s = "Hello\nWorld\nLearn\nJava";
System.out.println(s);

jdk13之后可以直接这样写:

String s = """
            Hello
            World
            Learn
            Java
           """;
System.out.println(s);

这样的字符串更加一目了然。

JDK14

instanceof模式匹配

该特性可以减少强制类型转换的操作,简化了代码,代码示例:

public class TestInstanceof{
    public static void main(String[] args){

        //jdk14之前的写法
        Object obj = new Integer(1);
        if(obj instanceof Integer){
            Integer i = (Integer)obj;
            int result = i + 10;
            System.out.println(i);
        }

        //jdk14新特性  不用再强制转换了
        //这里相当于是将obj强制为Integer之后赋值给i了
        if(obj instanceof Integer i){
            int result = i + 10;
            System.out.println(i);
        }else{
            //作用域问题,这里是无法访问i的
        }
    }
}

这个是预览版的功能所以需要使用下面命令编译和运行

编译:
    javac --enable-preview -source 14 TestInstanceof.java

运行:
    java --enable-preview TestInstanceof

友好的空指针(NullPointerException)提示

jdk14中添加了对于空指针异常友好的提示,便于开发者快速定位空指针的对象。示例代码:

class Machine{
    public void start(){
        System.out.println("启动");
    }
}

class Engine{
    public Machine machine;
}

class Car{
    public Engine engine;

}

public class TestNull{
    public static void main(String[] args){
        //这里会报出空指针,但是哪个对象是null呢?
        new Car().engine.machine.start();
    }
}

我们在运行上面代码的时候,错误信息就可以明确的指出那个对象为null了。此外,还可以使用下面参数来查看:

java -XX:+ShowCodeDetailsInExceptionMessages TestNull

这样编译器会明确的告诉开发者哪个对象是null。

record类型

之前在编写javabean类的时候,需要编写成员变量,get方法,构造方法,toString方法,hashcode方法,equals方法。这些方法通常会通过开发工具来生成,在jdk14中新增了record类型,通过该类型可以省去这些代码的编写。

jdk14编写User

public record User(String name,Integer age){}

通过反编译命令可以看到该字节码文件中的内容,User类是继承了Record类型:

javap -p -private user

编写测试类:

public class TestUser{
    public static void main(String[] args){
        User u = new User("ahzoo",18);
        System.out.println(u);
        System.out.println(u.name());
    }
}

这个是预览版的功能所以需要使用下面命令编译和运行

编译:
    javac --enable-preview -source 14 TestUser.java

运行:
    java --enable-preview TestUser

记录类型有自动生成的成员,包括:

  • 状态描述中的每个组件都有对应的private final字段。

  • 状态描述中的每个组件都有对应的public访问方法。方法的名称与组件名称相同。

  • 一个包含全部组件的公开构造器,用来初始化对应组件。

  • 实现了equals()和hashCode()方法。equals()要求全部组件都必须相等。

  • 实现了toString(),输出全部组件的信息。

JDK15

Sealed Classes

密封类和接口,作用是限制一个类可以由哪些子类继承或者实现。

  1. 如果指定模块的话,sealed class和其子类必须在同一个模块下。如果没有指定模块,则需要在同一个包下。

  2. sealed class指定的子类必须直接继承该sealed class。

  3. sealed class的子类要用final修饰。

  4. sealed class的子类如果不想用final修饰的话,可以将子类声明为sealed class。

Animal类,在指定允许继承的子类时可以使用全限定名

public sealed class Animal 
    permits Cat, Dog{//多个子类之间用,隔开

        public void eat(){}
}

Cat类

public final class Cat extends Animal{
    public void eat(){
        System.out.println("123");
    }
}

Dog类

public sealed class Dog extends Animal permits Husky {}

Husky类

public final class Husky extends Dog{
}

Test类

public class Test{
    public static void main(String[] args){
        Cat c = new Cat();
        c.eat();
        Dog d = new Dog();
    }
}

CharSequence新增的方法

该接口中新增了default方法isEmpty(),作用是判断CharSequence是否为空。

TreeMap新增方法

putIfAbsent、 computeIfAbsent 、computeIfPresent 、compute 、merge

文本块

文本块由预览版变为正式版

JDK16

包装类构造方法的警告

​ 使用包装类的构造方法在编译的时候会出现警告,不建议再使用包装类的构造方法。下面代码在javac编译之后会出现警告。

Integer i = new Integer(8);

不建议使用包装类作为锁对象,倘若使用包装类作为锁对象,在编译时会出现警告。

Integer i = 8;
synchronized(i){
}

新增日时段

在DateTimeFormatter.ofPattern传入B可以获取现在时间对应的日时段,上午,下午等

System.out.println(DateTimeFormatter.ofPattern("B").format(LocalDateTime.now()));

InvocationHandler新增方法

在该接口中添加了下面方法

public static Object invokeDefault(Object proxy, Method method, Object... args)

该方法可以调用父接口中defalut方法,比如有下面接口

interface Girl{
    default void eat(){
        System.out.println("cucumber");
    }

}

实现类

public class Lucy implements Girl{
    public void eat(){
        System.out.println("banana");
    }
}

测试类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test{
    public static void main(String[] args) {
        Girl girl = new Lucy();


        //不使用invokeDefault会调用重写的eat方法
        Girl proxy1 = (Girl)Proxy.newProxyInstance(girl.getClass().getClassLoader(),girl.getClass().getInterfaces(),
            (obj,method,params)->{
            Object invoke = method.invoke(girl);
            return invoke;
        });
        proxy1.eat();

        //使用invokeDefault会调用父接口中的default方法
        Girl proxy2 = (Girl)Proxy.newProxyInstance(Girl.class.getClassLoader(),new Class<?>[]{Girl.class},
            (obj,method,params)->{
            if (method.isDefault()) {
                return InvocationHandler.invokeDefault(obj, method, params);
            }
            return null;
        });
        proxy2.eat();

    }

}

JDK17

java17是一个LTS(long term support)长期支持的版本。

switch语法的变化(预览)

Sealed Classes

在jdk15中已经添加了Sealed Classes,只不过当时是作为预览版,经历了2个版本之后,在jdk17中Sealed Classes已经成为正式版了。Sealed Classes的作用是可以限制一个类或者接口可以由哪些子类继承或者实现。

参考文章:https://zhuanlan.zhihu.com/p/390679021

版权声明
本文依据 CC-BY-NC-SA 4.0 许可协议授权,请您在转载时注明文章来源为 Z次元 ,若本文涉及转载第三方内容,请您一同注明。
更多专栏文章推荐
知识积累
人非生而知之者,孰能无惑?惑而不从师,其为惑也,终不解矣。
JDK新版特性(9-11)
2025/1/30
将Maven项目组件上传到Maven中心仓(借助sonatype)
2024/6/8
JDK新版特性(18-21)
2025/2/7
评论区
发表评论

这里还没有评论哦

快来发一条评论抢占前排吧

JDK12
升级的switch语句
JDK13
升级的switch语句
文本块的变化
JDK14
instanceof模式匹配
友好的空指针(NullPointerException)提示
record类型
JDK15
Sealed Classes
CharSequence新增的方法
TreeMap新增方法
文本块
JDK16
包装类构造方法的警告
新增日时段
InvocationHandler新增方法
JDK17
switch语法的变化(预览)
Sealed Classes
目录
JDK12
升级的switch语句
JDK13
升级的switch语句
文本块的变化
JDK14
instanceof模式匹配
友好的空指针(NullPointerException)提示
record类型
JDK15
Sealed Classes
CharSequence新增的方法
TreeMap新增方法
文本块
JDK16
包装类构造方法的警告
新增日时段
InvocationHandler新增方法
JDK17
switch语法的变化(预览)
Sealed Classes
十玖八柒
每天进步多一点
欢迎到访φ(゜▽゜*)♪
最新评论
个人占星:

想给自己的网站弄个统计功能,但不会弄,头疼

永恒末匕:

好哇塞,这个厉害

十玖八柒:

测试图片发送

Corwin: @十玖八柒

哎 主要是我的个人网站用的是静态的cos 实现评论框还是有点困难

我的
个人主页
站点地图
RSS订阅
导航
十年之约
虫洞穿梭
全站友链
虚位以待
©2020 - 2025 By 十玖八柒 版权所有
豫ICP备20021466号