惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
N
News and Events Feed by Topic
量子位
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
Hugging Face - Blog
Hugging Face - Blog
S
Security Affairs
J
Java Code Geeks
Schneier on Security
Schneier on Security
Google Online Security Blog
Google Online Security Blog
TaoSecurity Blog
TaoSecurity Blog
小众软件
小众软件
S
SegmentFault 最新的问题
www.infosecurity-magazine.com
www.infosecurity-magazine.com
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
P
Privacy International News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
博客园 - 聂微东
T
Tor Project blog
博客园 - Franky
C
CERT Recently Published Vulnerability Notes
Cyberwarzone
Cyberwarzone
罗磊的独立博客
博客园_首页
The Cloudflare Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
腾讯CDC
Simon Willison's Weblog
Simon Willison's Weblog
S
Securelist
博客园 - 【当耐特】
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
博客园 - 司徒正美
AWS News Blog
AWS News Blog
WordPress大学
WordPress大学
Jina AI
Jina AI
G
GRAHAM CLULEY
V
V2EX
L
LINUX DO - 最新话题
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家

牛牛技术客栈

设计模式-备忘录模式 - OXOXTECH 牛牛技术客栈 设计模式-中介者模式 - OXOXTECH 牛牛技术客栈 Linux【Ubuntu】修改ssh默认端口 - OXOXTECH 牛牛技术客栈 设计模式-迭代器模式 - OXOXTECH 牛牛技术客栈 scheduled定时任务的三种基本实现方式 - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(三) - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(二) - OXOXTECH 牛牛技术客栈 Apriori - 基于关联规则的推荐算法(一) - OXOXTECH 牛牛技术客栈 基于JavaFX的桌面端网络调试工具 - OXOXTECH 牛牛技术客栈 Golang Channel的原理介绍 - OXOXTECH 牛牛技术客栈 Go语言Map的原理分析 - OXOXTECH 牛牛技术客栈 Go语言错误处理(panic)的最佳实践 - OXOXTECH 牛牛技术客栈 设计模式-解释器模式 - OXOXTECH 牛牛技术客栈 Redis报错Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. go-webpbin库在Linux报错failed to encode image to WebP: exit status 1.......的问题 exe4j 打包加密的jar - OXOXTECH 牛牛技术客栈 Go生成图形验证码示例 - OXOXTECH 牛牛技术客栈 澳门一天游:一日尽享东方与西方的交融之美 - OXOXTECH 牛牛技术客栈 设计模式-命令模式 - OXOXTECH 牛牛技术客栈 别再自己瞎写工具类了,SpringBoot内置工具类应有尽有 - OXOXTECH 牛牛技术客栈 中山一日游 - OXOXTECH 牛牛技术客栈 设计模式-责任链模式 - OXOXTECH 牛牛技术客栈 起舞吧,齐舞吧 - OXOXTECH 牛牛技术客栈 设计模式-组合模式 - OXOXTECH 牛牛技术客栈 Go语言Web开发|GoFrame框架入门笔记 - OXOXTECH 牛牛技术客栈 Java打包exe教程 - OXOXTECH 牛牛技术客栈 设计模式-代理模式 - OXOXTECH 牛牛技术客栈 MySQL存储过程的优缺点有哪些? - OXOXTECH 牛牛技术客栈 前端渲染优化有哪些? - OXOXTECH 牛牛技术客栈 HTTP状态码及其含义 - OXOXTECH 牛牛技术客栈 从浏览器地址栏输入url到显示页面的步骤 - OXOXTECH 牛牛技术客栈 TypeScript事件派发管理器 - OXOXTECH 牛牛技术客栈 MQTT保留消息的使用方法 - OXOXTECH 牛牛技术客栈 世界工程-港珠澳大桥游 - OXOXTECH 牛牛技术客栈 Golang逃逸分析 - OXOXTECH 牛牛技术客栈 设计模式-享元模式 - OXOXTECH 牛牛技术客栈 牛牛成长记录 - OXOXTECH 牛牛技术客栈 ffmpeg常用命令 - OXOXTECH 牛牛技术客栈 设计模式-外观模式 - OXOXTECH 牛牛技术客栈 设计模式-装饰器模式 - OXOXTECH 牛牛技术客栈 设计模式-桥接模式 - OXOXTECH 牛牛技术客栈 5周年恋爱纪念日 - OXOXTECH 牛牛技术客栈 2024新年快乐,龙腾四海 - OXOXTECH 牛牛技术客栈 迎接新年:除夕的美好时刻 - OXOXTECH 牛牛技术客栈 设计模式-适配器模式 - OXOXTECH 牛牛技术客栈 设计模式-原型模式 - OXOXTECH 牛牛技术客栈 设计模式-建造者模式 - OXOXTECH 牛牛技术客栈 设计模式-工厂模式 - OXOXTECH 牛牛技术客栈 设计模式-单例模式 - OXOXTECH 牛牛技术客栈 SpringBoot在Linux环境下发送163邮件失败(No appropriate protocol (protocol is disabled or cipher suites are inappropriate)) 海与日落 - OXOXTECH 牛牛技术客栈 Swagger比较常用的注解 - OXOXTECH 牛牛技术客栈 猫🐱牛 - OXOXTECH 牛牛技术客栈 2023年最后一个晚霞 - OXOXTECH 牛牛技术客栈 Linux(Centos)部署Nginx教程 - OXOXTECH 牛牛技术客栈 Linux MySQL下载安装详细教程(CentOS版) - OXOXTECH 牛牛技术客栈 JavaFx打包成exe - OXOXTECH 牛牛技术客栈 Flux脚本语言入门教程 - OXOXTECH 牛牛技术客栈 演唱会出图 - OXOXTECH 牛牛技术客栈 Netty TCP解决粘包拆包 - OXOXTECH 牛牛技术客栈 SpringBoot实现订单超时取消的几种方案 - OXOXTECH 牛牛技术客栈 详解Java并发中的各种锁 - OXOXTECH 牛牛技术客栈 SpringBoot集成支付宝支付 - OXOXTECH 牛牛技术客栈 雪花算法:分布式系统唯一ID生成算法 - OXOXTECH 牛牛技术客栈 Java解决空指针的神器Optional - OXOXTECH 牛牛技术客栈 与兴一起 - OXOXTECH 牛牛技术客栈 Jdk17安装+环境配置详细教程 - OXOXTECH 牛牛技术客栈 孤注一掷 - OXOXTECH 牛牛技术客栈 解决WinSCP经常断线重连 - OXOXTECH 牛牛技术客栈 内存不足导致Tomcat崩溃问题排查与解决办法 - OXOXTECH 牛牛技术客栈 influxDB初识,一个高效的时序数据库 - OXOXTECH 牛牛技术客栈 SpringBoot 服务接口限流方案 - OXOXTECH 牛牛技术客栈 Docker 安装 Portainer - OXOXTECH 牛牛技术客栈 Linux 安装Docker - OXOXTECH 牛牛技术客栈 物料宣传 - OXOXTECH 牛牛技术客栈 Java使用EMQX实现MQTT通信 - OXOXTECH 牛牛技术客栈 Java实现常见的排序算法 - OXOXTECH 牛牛技术客栈 FreeSwitch Windows安装教程 - OXOXTECH 牛牛技术客栈 MQTT单向SSL数据加密 - OXOXTECH 牛牛技术客栈 随性 - OXOXTECH 牛牛技术客栈 mysql报错Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre的解决方案 Git Push项目报 push to origin/master was rejected 错误解决方案 游行记——珠海金沙滩与金湖公园之行 - OXOXTECH 牛牛技术客栈 Tomcat:解决Tomcat启动警告:"无法将资源添加到Web应用程序缓存中....请考虑增加缓存空间" 的问题 - OXOXTECH 牛牛技术客栈 励骏庞都广场,迷一般的皇宫 - OXOXTECH 牛牛技术客栈 Docker 常用命令集合 - OXOXTECH 牛牛技术客栈 ElasticSearch Windows版-安装教程 - OXOXTECH 牛牛技术客栈 Java去除对象中为null的字段 - OXOXTECH 牛牛技术客栈 我和我的青春 - OXOXTECH 牛牛技术客栈 Java实现螺旋矩阵算法: - OXOXTECH 牛牛技术客栈 Java直接内存分配和释放的理解 - OXOXTECH 牛牛技术客栈 FreeSwitch将默认数据库迁移至MySQL - OXOXTECH 牛牛技术客栈 别错过路上的风景,别错过刹那间的深情! - OXOXTECH 牛牛技术客栈 Viewer.js:一款强大的图片预览组件 - OXOXTECH 牛牛技术客栈 Java JDK Proxy和CGLib动态代理示例 - OXOXTECH 牛牛技术客栈 redis常用命令 - OXOXTECH 牛牛技术客栈 SpringBoot查询IP归属地 - OXOXTECH 牛牛技术客栈 Spring 事务失效的六种情况 - OXOXTECH 牛牛技术客栈 #张艺兴每时每刻# - OXOXTECH 牛牛技术客栈 Nginx常用命令及具体应用 - OXOXTECH 牛牛技术客栈
Java17新特性详解与安装 - OXOXTECH 牛牛技术客栈
Mr.Potato · 2023-08-25 · via 牛牛技术客栈

前言

Java 17 是 2021 年 9 月 14 日正式发布的,距今也已经快2年多了,是一个长期支持(LTS)版本。Java 17 这个版本非常重要,Spring Framework 6.0 Spring Boot 3.0 最低支持都是 Java 17,搞Java开发肯定是离不开Spring这个主流的框架。下面这张图是 Oracle 官方给出的 Oracle JDK 支持的时间线,可以看得到Java17支持到2029年9月。

202308251456279645.webp

增强Switch

之前的 switch 写法如下:

String a = "jdk17";
     switch (a){
         case "jdk8":
             System.out.println("我是jdk8");
             break;
         case "jdk17":
             System.out.println("我是jdk17");
             break;
         default:
             System.out.println("未知");
             break;
     }

从jdk12后可以通过 switch 表达式来进行简化。使用箭头“->”,并且不需要每个 case break,大大提高了我们的编写效率,如下所示:

switch (a) {
            case "jdk8" -> System.out.println("我是jdk8");
            case "jdk17" -> System.out.println("我是jdk17");
            default -> System.out.println("未知");
        }

当我们需要赋值给一个变量的时候,不需要在每个case里头挨个赋值,其实 switch 也可以返回一个值,例如:

String a = "jdk17";
        String who = switch (a) {
            case "jdk8" -> "我是jdk8";
            case "jdk17" -> "我是jdk17";
            default -> "未知";
        };
        System.out.println(who);

输出:

我是jdk17

如果是匹配多个case 的话用逗号分开,例如:

String a = "jdk17";
        String who = switch (a) {
            case "jdk8","jdk17" -> "我是jdk家族";
            case "spring","spring boot" -> "我是spring家族";
            default -> "未知";
        };
 System.out.println(who);

如果你想在case里做不止一件事,比如在返回之前先进行一些计算或者打印操作。可以通过大括号来作为case块,最后的返回值使用关键字 yield 进行返回。

String a = "spring";
        String who = switch (a) {
            case "jdk8","jdk17" -> {
                System.out.println(1+1);
                yield "我是jdk家族";
            }
            case "spring","spring boot" -> {
                System.out.println(2+2);
                yield "我是spring家族";
            }
            default -> "未知";
        };
        System.out.println(who);

输出:

4
我是spring家族

以及之前的switch只支持 数值和字符串常量的匹配 ,而现在还支持对对象的类型来进行匹配,例如:

Object a = 888;
        String who = switch (a) {
            case null -> "is null";
            case Integer i -> String.format("i is %s",i);
            case String s -> String.format("s is string %s",s);
            default -> a.toString();
        };
        System.out.println(who);

输出:

i is 888

文本块

在Java17之前的版本里,如果我们需要定义一个字符串,比如一个JSON数据或者一些html等,基本都是采用拼接的方式去定义,大量的加号和转义的双引号非常的恶心且难看,例如:

String text = "{\n" +
                "  \"name\": \"小黑说Java\",\n" +
                "  \"age\": 18,\n" +
                "  \"address\": \"北京市西城区\"\n" +
                "}";

而从jdk15后这个写法才得以改善,只需要在前后加上 """ 。

String text = """
                {
                  "name": "小黑说Java",
                  "age": 18,
                  "address": "北京市西城区"
                }
                """;

显然,更方便,更简洁了。若是在文本块内加入空格或者换行之类的,请参考以下:

\s:表示空格
\:表示不换行
\s\:表示添加一个空格且不换行

instanceof增强

通常我们使用instanceof时,一般发生在需要对一个变量的类型进行判断,如果符合指定的类型,则强制类型转换为一个新变量。

之前的写法:

List<?> rows = selectMenuList(menu, getUserId()).getRows();
List<SysMenu> menus =  new ArrayList<>();
rows.forEach(r->{
   if (r instanceof SysMenu)
       menus.add((SysMenu)r);
});

jdk17后的写法:

List<?> rows = selectMenuList(menu, getUserId()).getRows();
List<SysMenu> menus =  new ArrayList<>();
rows.forEach(r->{
   if (r instanceof SysMenu sysMenu)
       menus.add(sysMenu);
});

Record关键字

record用于创建不可变的数据类。在这之前如果你需要创建一个存放数据的类,通常需要先创建一个Class,然后生成构造方法、getter、setter、hashCode、equals和toString等这些方法,或者使用Lombok来简化这些操作。而record就基本相当于实体类+Lombok的效果,但是 record 是不支持继承的,适合数据量少且不复杂的情况下使用。

创建一个实体类 Pon:

@Data
@AllArgsConstructor
public class Pon {
    private String name;
    private String nickName;
    private Integer addrNum;
}

然后进行一些简单的测试

public class JunitTest {
    @Test
    void test() {

        Pon pon = new Pon("张三", "小三", 65220);
        System.out.println(pon.getName());
        System.out.println(pon.getNickName());
        System.out.println(pon.getAddrNum());
    }
}

输出:

张三
小三
65220

以下是使用record代替前面的Pon类,record的属性不需要去定义,直接通过参数的形式设置。

public record RecordPon(String name, String nikName, Integer addrNum) {
  
}

接下来对RecordPon进行一些简单的测试

public class JunitTest {
    @Test
    void test() {
        RecordPon recordPon = new RecordPon("张三", "小三", 65220);
        System.out.println(recordPon.name());
        System.out.println(recordPon.nikName());
        System.out.println(recordPon.addrNum());
        RecordPon recordPon2 = new RecordPon("李四", "小四", 65220);
        System.out.println(recordPon2.name());
        System.out.println(recordPon2.nikName());
        System.out.println(recordPon2.addrNum());
    }
}

输出:

张三
小三
65220
李四
小四
65220

当然了,record 同样也有构造方法,可以在构造方法中对数据进行一些操作,例如:

public record RecordPon(String name, String nikName, Integer addrNum) {
    public RecordPon {
        if (Objects.equals(name, ""))
            System.err.println( "name is not null");
    }
}
总结:Lombok record 是不同的工具,服务于不同的目的。此外,Lombok 更加灵活,它可以用于 record 受限的场景。

Helpful NullPointerExceptions

Java8 我们如果遇到NPE,通常只会输出将显示NullPointerException发生的行号,但不知道哪个方法调用时产生的null,必须通过调试的方式找到。对于复杂度高的代码来讲就非常耗时,而从Helpful NullPointerExceptions可以在我们遇到NPE时节省一些时间,会准确显示发生NPE的精确位置,比如以下代码会发生一个NPE:

public class JunitTest {
    @Test
    void test() {
        String str = null;
        int length = str.length();
    }
}

输出:

202308231347386948.webp

密封类 sealed class

密封类是一种特殊的类,它用来表示受限的类继承结构,即一个类只能有有限的几种子类,而不能有任何其他类型的子类。这样可以让我们更好的控制哪些类可以对我定义的类进行扩展,而在这之前一个类要么是可以被extends的,要么是final的任何人都不能继承的,只有这两种选项,没有什么灵活性。首先创建Animal、DogCat

public abstract class Animal {
     public void put(){
        System.out.println("我是动物");
    }
}
public class Dog extends Animal {

}
public class Cat extends Animal {

}

在这里这个Animal 是可以被任何一个类继承的,例如:

public class JunitTest {
    @Test
    void test() {
        Cat cat = new Cat();
        Dog dog = new Dog();
        Animal animal = cat;
        Animal animal2 = dog;
        class china extends Animal{}
        class usa extends Dog{}
    }
}

除了DogCat类能继承之外,这里创建的china类也能继承Animal类,usa类也继承Dog类。ok这本来没什么问题,就是这个关系有点不正常,国家怎么能继承于动物呢?

Jdk17中通过密封类可以解决这个问题,主要就这几个关键字:

  • final:不允许被继承
  • sealed:密封类(需要指定哪个类可以扩展它)
  • non-sealed:可以被任何类继承
  • permits :指定哪个类可以继承于我

现在我们将上面的Animal 类改成密封类,例如:

public sealed class Animal permits Dog{
    public void put(){
        System.out.println("我是动物");
    }
}

此处的Animal是密封类,指定了只有Dog类可以继承它

public sealed class Dog extends Animal permits DogSon{
}

而此时Dog类也是一个密封类,它也指定了只有DogSon这个类可以继承它。这里做个小测试,创建一个BigDog类并继承Dog

202308241403041549.webp

直接告诉你  密封层次结构中不允许使用"BigDog"  ,需要给BigDog指定这个permits ,其他亦是如此,除非你定义成non-sealed

备注👣:密封类子类必须是 final类、sealed类或non-sealed类,并且 父类子类 必须在同一个包下

开始安装

下载安装可以参考我之前的文章:《Jdk17安装+环境配置详细教程【Windows》

总结

以上主要介绍了Jdk17的一些主流的新特性,更多具体特性请参考官方文档: https://www.oracle.com/java/technologies/javase/17-relnote-issues.html#NewFeature