首页 > 其他分享 >JDK17 新特性

JDK17 新特性

时间:2024-06-14 09:56:07浏览次数:9  
标签:case String JDK17 特性 println public out

引言

JDK 版本升级的非常快,写这篇博客时已经到 JDK22 了,而 Java 17 继续作为业界最常用的长期支持(LTS)版本。目前 Java 11 是最受欢迎的LTS 版本,有超过 56% 的应用程序在生产中使用它,而 Java 8 的使用率为 33% 且逐年下降,Java 17 的使用率在一年内增长了 430 %,有超过9%的应用程序在生产中使用 Java 17。

简言之,JDK11(当前主流)、JDK8(逐渐淘汰)、JDK17(未来趋势)

作为 Java 初学者,学习时建议使用当前主流或更高一些的 JDK 版本,这样可以学习和体验 JDK 新特性带来的便利,也为未来从事生产应用开发积累经验。

JDK17新特性1 - 文本块(推荐指数:⭐️⭐️⭐️⭐️⭐️)

这个更新非常实用。在没有这个特性之前,编写长文本非常痛苦。虽然 IDEA 等集成开发工具可以自动处理,但最终效果仍然丑陋,充满拼接符号。现在,通过字符串块,我们可以轻松编写JSON、HTML、SQL等内容,效果更清爽。

这个新特性值得五颗星评价,因为它让我们只需关注字符串本身,而无需关心拼接操作。

之前写法如下:

/**
 * 使用JDK8返回HTML文本
 *
 * @return 返回HTML文本
 */
public static final String getHtmlJDK8() {
    return "<html>\n" +
        " <body>\n" +
        " <p>Hello, world</p>\n" +
        " </body>\n" +
        "</html>";
}

JDK17写法如下:

/**
 * 使用JDK17返回HTML文本
 * @return 返回HTML文本
 */
public static final String getHtmlJDK17() {
    return """
        <html>
        <body>
        <p>Hello, world</p>
        </body>
        </html>
        """;
}

JDK17新特性2 - NullPointerException 增强(推荐指数:⭐️⭐️⭐️⭐️⭐️)

这一功能非常强大且实用,相信每位 Java 开发者都期待已久。空指针异常(NPE)一直是Java程序员的痛点,因为报错信息无法直观地指出哪个对象为空,只抛出一个 NullPointerException 和一堆堆栈信息,定位问题耗时且麻烦。尤其在遇到喜欢级联调用的代码时,逐行排查更是令人头疼。如果在测试环境中,可能还需通过远程调试查明空对象,费时费力。为此,阿里的编码规范甚至不允许级联调用,但这并不能彻底解决问题。Java17 终于在这方面取得了突破,提供了更详细的空指针异常信息,帮助开发者迅速定位问题源头。

使用举例:

public static void main(String[] args) {
    try {
        //简单的空指针
        String str = null;
        str.length();
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        //复杂一点的空指针
        var arr = List.of(null);
        String str = (String)arr.get(0);
        str.length();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

运行结果

JDK17新特性3 - Records(推荐指数:⭐️⭐️⭐️⭐️)

在Java中,POJO对象(如DO、PO、VO、DTO等)通常包含成员变量及相应的Getter和Setter方法。尽管可以通过工具或IDE生成这些代码,但修改和维护仍然麻烦。Lombok 插件为此出现,能够在编译期间自动生成Getter、Setter、hashcode、equals和构造函数等代码,使用起来方便,但对团队有依赖要求。为此,Java引入了标准解决方案:Records。它通过简洁的语法定义数据类,大大简化了POJO类的编写,如下所示。虽然hashcode和equals方法仍需手动编写,但IDE能够自动生成。这一特性有效解决了模板代码问题,提升了代码整洁度和可维护性。

使用举例

/**
 *
 * @param stuId     学生ID
 * @param stuName   学生名称
 * @param stuAge    学生年龄
 * @param stuGender 学生性别
 * @param stuEmail  学生邮箱
 */
public record StudentRecord(Long stuId,
                            String stuName,
                            int stuAge,
                            String stuGender,
                            String stuEmail) {
    public StudentRecord {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        StudentRecord record = new StudentRecord(1L, "张三", 16, "男", "[email protected]");
        System.out.println(record);
    }
}

JDK17新特性4 - 全新的switch表达式(推荐指数:⭐️⭐️⭐️⭐️)

在 Java12 的时候就引入了switch表达式,注意这里是表达式,而不是语句,原来的switch是语句。如果不清楚两者的区别的话,最好先去了解一下。主要的差别就是就是表达式有返回值,而语句则没有。再配合模式匹配,以及yield和“->”符号的加入,全新的switch用起来爽到飞起来。

使用举例

public class SwitchDemo {
    /**
     * 在JDK8中获取switch返回值方式
     *
     * @param week
     * @return
     */
    public int getByJDK8(Week week) {
        int i = 0;
        switch (week) {
            case MONDAY, TUESDAY:
                i = 1;
                break;
            case WEDNESDAY:
                i = 3;
                break;
            case THURSDAY:
                i = 4;
                break;
            case FRIDAY:
                i = 5;
                break;
            case SATURDAY:
                i = 6;
                break;
            case SUNDAY:
                i = 7;
                break;
            default:
                i = 0;
                break;
        }

        return i;
    }

    /**
     * 在JDK17中获取switch返回值
     *
     * @param week
     * @return
     */
    public int getByJDK17(Week week) {
        // 1, 现在的switch变成了表达式,可以返回值了,而且支持yield和->符号来返回值
        // 2, 再也不用担心漏写了break,而导致出问题了
        // 3, case后面支持写多个条件
        return switch (week) {
            case null -> -1;
            case MONDAY -> 1;
            case TUESDAY -> 2;
            case WEDNESDAY -> 3;
            case THURSDAY -> {yield 4;}
            case FRIDAY -> 5;
            case SATURDAY, SUNDAY -> 6;
            default -> 0;
        };
    }

    private enum Week {
        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY,
        SUNDAY
    }
}

JDK17新特性5 - 私有接口方法(推荐指数:⭐️⭐️⭐️)

从Java8开始,允许在interface里面添加默认方法,其实当时就有些小困惑,如果一个default方法体很大怎么办,拆到另外的类去写吗?实在有些不太合理,所以在Java17里面,如果一个default方法体很大,那么可以通过新增接口私有方法来进行一个合理的拆分了,为这个小改进点个赞。

使用举例

public interface PrivateInterfaceMethod {
    /**
     * 接口默认方法
     */
    default void defaultMethod() {
        privateMethod();
    }

    // 接口私有方法,在Java8里面是不被允许的,不信你试试
    private void privateMethod() {
    }
}

JDK17新特性6 - 模式匹配(推荐指数:⭐️⭐️⭐️⭐️)

在JDK 17中,模式匹配主要用于instanceof表达式。模式匹配增强了instanceof的语法和功能,使类型检查和类型转换更加简洁和高效。在传统的Java版本中,我们通常使用instanceof结合类型转换来判断对象类型并进行处理,这往往会导致冗长的代码。

以前的写法如下:

/**
 * 旧式写法
 *
 * @param value
 */
public void matchByJDK8(Object value) {
    if (value instanceof String) {
        String v = (String)value;
        System.out.println("遇到一个String类型" + v.toUpperCase());
    } else if (value instanceof Integer) {
        Integer v = (Integer)value;
    System.out.println("遇到一个整型类型" + v.longValue());
    }
}

JDK17的写法如下:

/**
 * 转换并申请了一个新的变量,极大地方便了代码的编写
 *
 * @param value
 */
public void matchByJDK17(Object value) {
    if (value instanceof String v) {
        System.out.println("遇到一个String类型" + v.toUpperCase());
    } else if (value instanceof Integer v) {
        System.out.println("遇到一个整型类型" + v.longValue());
    }
}

JDK17新特性7 - 集合类的工厂方法(推荐指数:⭐️⭐️⭐️⭐️⭐️)

在Java8的年代,即便创建一个很小的集合,或者固定元素的集合都是比较麻烦的,为了简洁一些,有时我甚至会引入一些依赖。

以前的写法如下:

Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");

JDK17的写法如下:

Set<String> set = Set.of("a", "b", "c");

JDK17其他新特性

新的String方法
  • repeat:重复生成字符串
  • isBlank:不用在引入第三方库就可以实现字符串判空了
  • strip:去除字符串两边的空格,支持全角和半角,之前的trim只支持半角
  • lines:能根据一段字符串中的终止符提取出行为单位的流
  • indent:给字符串做缩进,接受一个int型的输入
  • transform:接受一个转换函数,实现字符串的转换
Stream API的增强

增加takeWhile, dropWhile, ofNullable, iterate以及toList的API,越来越像一些函数式语言了。

用法举例

// takeWhile 顺序返回符合条件的值,直到条件不符合时即终止继续判断,
// 此外toList方法的加入,也大大减少了节省了代码量,免去了调用collect(Collectors::toList)方法了
List<Integer> list = Stream.of(2,2,3,4,5,6,7,8,9,10)
        .takeWhile(i->(i%2==0)).toList(); // 返回2, 2

// dropWhile 顺序去掉符合条件的值,直到条件不符合时即终止继续判断
List<Integer> list1 = Stream.of(2,2,3,4,5,6,7,8,9,10)
        .dropWhile(i->(i%2==0)).toList(); //返回3, 4, 5, 6, 7, 8, 9, 10

// ofNullable,支持传入空流,若没有这个且传入一个空流,那么将会抛NPE
var nullStreamCount = Stream.ofNullable(null).count(); //返回0

// 以下两行都将输出0到9
Stream.iterate(0, n -> n < 10, n -> n + 1).forEach(x -> System.out.println(x));
Stream.iterate(0, n -> n + 1).limit(10).forEach(x -> System.out.println(x));
全新的HttpClient

这个API首次出现在9之中,不过当时并非是一个稳定版本,在Java11中正式得到发布,所以在Java17里面可以放心地进行使用。原来的JDK自带的Http客户端真的非常难用,这也就给了很多像okhttp、restTemplate、Apache的HttpClient和feign这样的第三方库极大的发挥空间,几乎就没有人愿意去用原生的Http客户端的。但现在不一样了,感觉像是新时代的API了。FluentAPI风格,处处充满了现代风格,用起来也非常地方便,再也不用去依赖第三方的包了,就两个字,清爽。

// 同步请求
HttpClient client = HttpClient.newBuilder()
    .version(Version.HTTP_1_1)
    .followRedirects(Redirect.NORMAL)
    .connectTimeout(Duration.ofSeconds(20))
    .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
    .authenticator(Authenticator.getDefault())
    .build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body()); 
// 异步请求
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://foo.com/"))
    .timeout(Duration.ofMinutes(2))
    .header("Content-Type", "application/json")
    .POST(BodyPublishers.ofFile(Paths.get("file.json")))
    .build();
client.sendAsync(request, BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println);

jshell

在新的JDK版本中,支持直接在命令行下执行java程序,类似于python的交互式REPL。简而言之,使用 JShell,你可以输入代码片段并马上看到运行结果,然后就可以根据需要作出调整,这样在验证一些简单的代码的时候,就可以通过jshell得到快速地验证,非常方便。

java命令直接执行java文件

在现在可以直接通过执行java xxx.java,即可运行该java文件,无须先执行javac,然后再执行java,是不是又简单了一步。

ZGC

在ParallelOldGC、CMS和G1之后,JDK 11引入了全新的ZGC(Z Garbage Collector)。这个名字本身就显得很牛。官方宣称ZGC的垃圾回收停顿时间不超过10ms,能支持高达16TB的堆空间,并且停顿时间不会随着堆的增大而增加。

那么,ZGC到底解决了什么问题?Oracle官方介绍它是一个可伸缩的低延迟垃圾回收器,旨在降低停顿时间,尽管这可能会导致吞吐量的降低。不过,通过横向扩展服务器可以解决吞吐量问题。官方已建议ZGC可用于生产环境,这无疑将成为未来的主流垃圾回收器。

要了解更多,请参阅官方文档https://docs.oracle.com/en/java/javase/17/gctuning/z-garbage-collector.html#GUID-9957D441-A99A-4CF5-9522-393E6DE7D898

标签:case,String,JDK17,特性,println,public,out
From: https://www.cnblogs.com/binbingg/p/18247201

相关文章

  • Java 17 新增的语法特性
    Java17新增的语法特性目录Java17新增的语法特性JEP与ProjectAmber引言1.Records[JEP395]2.switch表达式与yield[JEP361]3.用于instanceof的模式匹配[JEP394]4.文本块[JEP378]5.密封类[JEP409]Java17的其他主要改进稳定版的ZGC垃圾回收器主流Java开发框架支持更......
  • Java 21新增的语法特性
    Java21新增的语法特性目录Java21新增的语法特性引言record模式[JEP440]用于switch的模式匹配[JEP441]序列集合[JEP431]虚拟线程[JEP444]Java21的其他改进说明1:本文大量参考了JEP文档与Oracle官方文档,部分文字直接引自这两个文档并进行了适当的修改。说明2:本文代码详......
  • 新增的JDK17语法特性
    一、引入从springboot3.0开始,已经不支持JDK8了,从3.0开始,转变为JDK17了解详情点击官方博客链接:https://spring.io/blog/2022/01/20/spring-boot-3-0-0-m1-is-now-available?spm=a2c6h.12873639.article-detail.24.766d46b40LM1IVhttps://spring.io/blog/2022/01/20/spring-boo......
  • C++ 新特性 | C++ 11 | typename关键字
    文章目录一、typename关键字前言:在C++的模板编程中,typename关键字扮演着至关重要的角色。它主要用于指示编译器将一个特定的标识符解释为类型名称,而不是变量名或其他实体。本文将深入探讨typename的用法,帮助读者更好地理解其在模板编程中的作用。一、typename关......
  • JDK8新特性之Lambda表达式
    Lambda,音标[ˈlamdə],中文翻译“拉姆达”,第11个希腊字母λ(大写Λ)。1.引入原因JDK8引入Lambda表达式是为了简化匿名类相关代码。当接口比较简单,只有一个方法时,我们也不得不写许多无关业务的代码来实现匿名类。而Lambda表达式却允许将功能(functionality)视作方法参数或者视代......
  • 【CMake系列】08-debug release特性设置
    在构建的程序版本中,一共有debugreleaseminisizerelwithDebugInfo四种,其中我们主要使用到就是debugrelease两种,这两种存在着一定的不同,debug版本用于调试,有调试信息,方便调试,体积也更大;release版本用于发布,体积更小;在使用cmake针对debugrelease配置时也存在一定的不......
  • MySQL之高级特性(一)
    高级特性外键约束InnoDB是目前MySQL中唯一支持外键的内置存储引擎,所以如果需要外键支持那选择就不多了。使用外键是有成本的。比如外键通常都要求每次在修改数据时都要在另一张表中多执行一次查找操作。虽然InnoDB强制外键使用索引,但还是无法消除这种约束检查的开销。如果......
  • 【Java之JDK8新特性】
    文章目录一、Java8中的Lambda表达式如何改善Java代码?二、在Java8中,接口有哪些新特性?三、如何使用Java8的StreamAPI进行集合处理?四、Java8的Optional类有什么用途?五、Java8中Date-TimeAPI的改进有哪些?六、Java8中的方法引用是什么,它有什么好处?七、Java8中的Compl......
  • 算法 | 剪枝函数以及几种形式&回溯法和分支限界法的区别&算法特性&分支限界法的思想&
    whatis剪枝函数?是对该问题能否得到最优解或者可行解的约束限界函数:最优解约束函数:可行解回溯法和分支限界法的区别:异:回溯法分支限界法一次生成/扩展一个结点一次生成所有的孩子结点BFSDFS/最小耗费优先找到所有解找到最优解同:均需要定义解空间,解空间的组织结构一般......
  • C++缺省参数、缺省参数的概念、缺省参数的分类、函数重载、函数重载的概念、C++支持函
    文章目录前言一、缺省参数1.缺省参数的概念2.缺省参数的分类二、函数重载1.函数重载的概念2.C++支持函数重载的原理三、引用1.引用的概念2.引用的特性3.常引用4.引用的使用场景5.传值和传引用效率比较6.引用和指针的区别总结前言C++缺省参数、缺省参数......