玩转微服务-基础篇-JDK17实用特性

这篇具有很好参考价值的文章主要介绍了玩转微服务-基础篇-JDK17实用特性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 文档及下载地址

OpenJDK Java 17 下载:https://jdk.java.net/archive/

OpenJDK Java 17 文档:https://openjdk.java.net/projects/jdk/17/

二. 特性功能

1. VAR 类型推导

JDK 10 的新特性, 这里说明下

  • var 来支持局部变量的类型推断,var 不是关键字,且只能用于局部变量;

  • var 不能用于字段、方法参数、构造方法参数、方法返回值,也不能用于 catch 参数,也不能用作类名接口名;

  • 可以用 for 循环和增强 for 循环里

代码 Demo:

public class Jdk17Demo {
    private var name;  // error

    Jdk17Demo(var name) {  // error
        this.name = name;
    }

    void text(var str) {  // error
        var st = "";
        var testList = new ArrayList<>();
        for (var st : testList) {
            System.out.println(st);
        }
    }
}

2. instanceof 模式匹配

instanceof 最常用的是用来判断 Object 类型,然后强转具体类型

private static void instanceDemo (Object obj) {
    if (obj instanceof String str) {
        // String str = (String) obj;  以前需要强制转换
        System.out.println("字符串的值:" + str);
    }
}

3. JEP 406:switch 的类型匹配 (预览)

部分还是预览功能,不建议大量使用,如:类型推导自动赋值,空值判定等

String PatternSwitch(Object o) {
    return switch (o) { // 预览版的不能使用
        case Integer i -> String.format("int %d", i);
        case Long l -> String.format("long %d", l);
        case Double d -> String.format("double %f", d);
        case String s -> String.format("String %s", s);
        default -> o.toString();
    };
}

void test(String tst) {
    var st = switch (tst) {
        case null -> "null";  // 预览版的不能使用
        case "张三" -> "张三";
        case "李四" -> "李四";
        case "王五" -> {
            //注意如果需要多条语句,需要在花括号内进行,在switch表达式中,
            // 如果多条语句,最后的值返回需要使用yield关键字进行返回
            yield "王五";	//注意这里返回的关键字不是return,而是yield 以前是break
        }
        default -> "赵六";
    };
    System.out.println(st);
}

4. 文本块 Text Blocks

字符串的拼接以前需要使用+进行连接,不方便阅读,现在:

public void now() {
    var address="shanxi";
    String jsonText = """
            {
              "name": "张三",
              "address": "${address}"
            }
            """;
    System.out.println(jsonText.formatted(address)); // 使用字符串的formatted 替换
}

5. 增强的伪随机数生成器

可以使用 Random、ThreadLocalRandom 和 SplittableRandom 来生成随机数。不过,这 3 个类都各有缺陷

伪随机数生成器(pseudorandom number generator,PRNG),又称为确定性随机位生成器(deterministic random bit generator,DRBG),是用来生成接近于绝对随机数序列的数字序列的算法。一般来说,PRNG 会依赖于一个初始值,也称为种子,来生成对应的伪随机数序列。只要种子确定了,PRNG 所生成的随机数就是完全确定的,因此其生成的随机数序列并不是真正随机的。

就目前而言,PRNG 在众多应用都发挥着重要的作用,比如模拟(蒙特卡洛方法),电子竞技,密码应用。

这次增加了 RandomGenerator 接口,为所有的 PRNG 算法提供统一的 API,并且可以获取不同类型的 PRNG 对象流。同时也提供了一个新类 RandomGeneratorFactory 用于构造各种 RandomGenerator 实例,在 RandomGeneratorFactory 中使用 ServiceLoader.provider 来加载各种 PRNG 实现。

//通过 RandomGeneratorFactory.of(“随机数生成算法”) 方法获得生成器
RandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of("L128X256MixRandom");
// 使用时间戳作为随机数种子
RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
// 生成0-9随机数
System.out.println(randomGenerator.nextInt(10));

获取所有的随机数算法

RandomGeneratorFactory.all().forEach(factory -> {
    System.out.println(factory.group() + ":" + factory.name());
});

6. 密封类 sealed class

限制哪些其他类或接口可以扩展或实现它们。提供一种比访问修饰符更具声明性的方式来限制超类的使用,

public abstract sealed class Furit permits Apple,Pear {

}

public non-sealed class Apple extends Furit {

}

public final class Pear extends Furit {

}
  • 在定义 Furit 时通过关键字 sealed 声明为密封类,通过 permits 可以指定 Apple,Pear 类可以进行继承扩展。

  • 指定的类 permits 必须位于超类附近:在同一个模块中(如果超类在命名模块中)或在同一个包中(如果超类在未命名模块中)。当 permits 的子类的大小和数量较小时,可以将它们声明在与密封类相同的源文件中,同时可以省略 permits 语句,Java 编译器将从源文件中的声明推断出 permits 的子类。

  • 指定的类 permits 必须具有规范名称,否则会报告编译时错误。这意味着匿名类和本地类不能成为密封类的子类型。

  • 密封类对其允许的子类施加三个约束:

      1. 密封类及其允许的子类必须属于同一个模块,并且如果在未命名的模块中声明,则必须属于同一个包。
      1. 每个允许的子类都必须直接扩展密封类。
      1. 每个允许的子类都必须使用修饰符来描述它如何传播由其超类发起的密封:
      • 可以声明允许的子类 final 以防止其在类层次结构中的一部分被进一步扩 展。(记录类是隐式声明的 final。)
      • 可以声明允许的子类 sealed 以允许其层次结构的一部分比其密封的超类所设想的扩展得更远,但以受限制的方式。
      • 可以声明一个允许的子类 non-sealed,以便它的层次结构部分恢复为对未知子类的扩展开放。密封类不能阻止其允许的子类这样做。(修饰符 non-sealed 是 为 Java 提出的第一个连字符关键字。)

类模型

public abstract sealed class Shape
    permits Circle, Rectangle, Square, WeirdShape { ... }

public final class Circle extends Shape { ... }

public sealed class Rectangle extends Shape
    permits TransparentRectangle, FilledRectangle { ... }
public final class TransparentRectangle extends Rectangle { ... }
public final class FilledRectangle extends Rectangle { ... }

public non-sealed class Square extends Shape { ... }

public class WeirdShape extends Square { ... }

密封和记录类 的配合使用


public sealed interface Expr
    permits ConstantExpr, PlusExpr, TimesExpr, NegExpr { ... }

public record ConstantExpr(int i)       implements Expr { ... }
public record PlusExpr(Expr a, Expr b)  implements Expr { ... }
public record TimesExpr(Expr a, Expr b) implements Expr { ... }
public record NegExpr(Expr e)           implements Expr { ... }

7. NullPointerExceptions 优化

会精确显示空指针报错的位置

8. Stream.toList()

Stream 转换成 List,需要使用 Collectors.toList(),代码非常冗长,

private static void before17() {
    Stream<String> stream = Stream.of("a", "b", "c");
    List<String> stringList =  stream.collect(Collectors.toList());
    for(String s : stringList) {
        System.out.println(s);
    }
}
private static void now17() {
    Stream<String> stream = Stream.of("a", "b", "c");
    List<String> stringList =  stream.toList();
    for(String s : stringList) {
        System.out.println(s);
    }
}

9. Records

Records 的目标是扩展 Java 语言语法,Records 为声明类提供了一种紧凑的语法,用于创建一种类中是“字段,只是字段,除了字段什么都没有”的类。 只读类

record 不会放堆里 所以不用垃圾回收 , 解决的是堆内存中放太多无用的类。?

record Person (String firstName, String lastName) {}

Demo

public record TestRecord(String name, String password) {
    //再定义一个构造方法
    public TestRecord(String name) {
        this(name, null);
    }

    //额外定义的方法
    public String nameToUppercase() {
        return this.name.toUpperCase();
    }

    //静态方法
    public static String nameAddPassword(TestRecord user1) {
        return user1.name + user1.password;
    }

    public static void main(String[] args) {
        TestRecord user = new TestRecord("XiaoMing", "123456");

        System.out.println(user.nameToUppercase());
        System.out.println(TestRecord.nameAddPassword(user));

        TestRecord userAnotherConstructor = new TestRecord("hello");
        System.out.println(userAnotherConstructor);
    }
}

10. JEP 415:指定上下文的反序列化过滤器

允许在反序列化时,通过一个过滤配置,来告知本次反序列化允许或者禁止操作的类,反序列化时碰到被禁止的类,则会反序列化失败。

1. 反序列化示例

假设 Dog 类中的 Poc 是恶意构造的类,但是正常反序列化是可以成功的。

package com.wdbyte.java17;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author niulang
 */
public class JEP415 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Dog dog = new Dog("哈士奇");
        dog.setPoc(new Poc());
        // 序列化 - 对象转字节数组
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
            objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // 反序列化 - 字节数组转对象
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object object = objectInputStream.readObject();
        System.out.println(object.toString());
        // Dog{name='哈士奇'}
    }
}

class Dog implements Serializable {
    private String name;
    private Poc poc;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" + "name='" + name + '\'' + '}';
    }
		// get...set...
}

class Poc implements Serializable{

}

2. 反序列化过滤器

在 Java 17 中可以自定义反序列化过滤器,拦截不允许的类。

package com.wdbyte.java17;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author niulang
 */
public class JEP415 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Dog dog = new Dog("哈士奇");
        dog.setPoc(new Poc());
        // 序列化 - 对象转字节数组
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
            objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // 反序列化 - 字节数组转对象
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        // 允许 com.wdbyte.java17.Dog 类,允许 java.base 中的所有类,拒绝其他任何类
        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
                        "com.wdbyte.java17.Dog;java.base/*;!*");
        objectInputStream.setObjectInputFilter(filter);
        Object object = objectInputStream.readObject();
        System.out.println(object.toString());
    }
}

class Dog implements Serializable {
    private String name;
    private Poc poc;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" + "name='" + name + '\'' + '}';
    }
		// get...set...
}

class Poc implements Serializable{
}

出现异常

Exception in thread "main" java.io.InvalidClassException: filter status: REJECTED
	at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1412)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2053)
	at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1907)
	....

11. 恢复始终严格的浮点语义

strictfp 是 Java 中的一个关键字,大多数人可能没有注意过它,它可以用在类、接口或者方法上,被 strictfp 修饰的部分中的 float 和 double 表达式会进行严格浮点计算。文章来源地址https://www.toymoban.com/news/detail-752302.html


public class test {
    public static void main(String[] args) {
        testStrictfp();
    }

    public strictfp static void testStrictfp() {
        float aFloat = 0.6666666666666666666f;
        double aDouble = 0.88888888888888888d;
        double sum = aFloat + aDouble;
        System.out.println("sum: " + sum);
    }
}

到了这里,关于玩转微服务-基础篇-JDK17实用特性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JDK17新特性之--JDK9到JDK17 String 新增的新方法

    JDK9之后对String底层存储数据结构进行了重大的修改 1 ,同步也增加了许多新的方法,主要有Text Blocks、chars()、codePoints()、describeConstable()、formatted()、indent()、isBlank()、isEmpty()、lines()、repeat()、strip()、stripLeading()、stripIndent()、stripTrailing()、translateEscapes(),接下来就逐一看看每个

    2024年02月04日
    浏览(31)
  • JDK 8 和 JDK 17 的区别和新特性

    Java是一门广泛使用的编程语言,拥有着丰富的生态系统和大量的开发者。Java的官方实现是Oracle公司的JDK(Java Development Kit),目前最新版本是JDK 17,而JDK 8是一个长期支持版本(LTS)。 JDK 8于2014年发布,引入了许多重要的新特性,如Lambda表达式、Stream API和新的日期时间API等

    2024年02月06日
    浏览(27)
  • JDK8,JDK11,JDK17,JDK21及中间版本主要更新特性

    官方地址: https://www.oracle.com/java/technologies/java-se-support-roadmap.html 从上图可以很清晰得可以看出,JDK7,JDK8,JDK11,JDK17,JDK21是长期维护的版本。从目前来看,JDK8到2023年已经有将近10年的历史了,大多数依据JDK8的相关技术内容已经很成熟了,但是大家也看到,JDK在不断地迭代,JD

    2024年02月21日
    浏览(48)
  • JDK8到JDK17有哪些吸引人的新特性?

    作者:京东零售 刘一达 2006年之后SUN公司决定将JDK进行开源,从此成立了OpenJDK组织进行JDK代码管理。任何人都可以获取该源码,并通过源码构建一个发行版发布到网络上。但是需要一个组织审核来确保构建的发行版是有效的, 这个组织就是JCP(Java Community Process)。2009年,SUN公

    2023年04月18日
    浏览(40)
  • 走近JDK 17,探索最新Java特性,拥抱未来编程!

    大家好,我是小米,一个热爱技术分享的程序员。今天,我将为大家介绍一下JDK 17的新特性。JDK 17是Java开发工具包的一个重要版本,其中包含了许多令人激动的新功能和改进。在这篇文章中,我将详细介绍JDK 17中的各项特性,并说明它们在电商应用场景中的应用。 密封类(

    2024年02月11日
    浏览(33)
  • JDK8、JDK11、JDK17和JDK21这几个版本更新的主要特性

    JDK8 是 Java 的一个重大更新版本,引入了一系列新特性和改进,主要包括: Lambda 表达式: Lambda 表达式允许我们以简洁、函数式的方式编写代码,使代码更易于理解和维护。- Stream API : Stream API 提供了一套声明式处理数据的方式,使得对集合和数组的操作更加直观和高效。

    2024年04月29日
    浏览(38)
  • JDK8-JDK17中的新特性(var类型推断、模式匹配、Record、密封类)

    新的语法结构,勾勒出了 Java 语法进化的一个趋势,将开发者从 复杂、繁琐 的低层次抽象中逐渐解放出来,以更高层次、更优雅的抽象,既 降低代码量 ,又避免意外编程错误的出现,进而提高代码质量和开发效率。 1.1 Java的REPL工具: jShell命令 JDK9的新特性 Java 终于拥有了

    2024年02月06日
    浏览(40)
  • 主流JDK性能大比拼;Zulu OpenJDK/OpenJDK/Oracle JDK/GraalVM CE

    市面上可供选择的JVM发行版还是有不少的。选择合适的JVM需要考虑不同的因素。性能是其中一个重要的因素。靠谱的性能研究是很困难的。在本文中,我创建了一个测试,在不同的JVM上执行对比测试。测试程序包括Spring Boot REST应用,使用Prometheus监控JVM并使用Grafana可视化。下

    2024年02月09日
    浏览(32)
  • 【Java基础系列】JDK21新特性

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月04日
    浏览(33)
  • Mac端安装JDK、JDK11、OpenJDK11

    原文链接:Mac端安装JDK、JDK11、OpenJDK11 | Elvin 为了编译JDK,所以才安装JDK ​ macOS Ventura 13.2 ​ 可以有多个JDK,我的本地就有JDK 8,后面会介绍如何无缝切换JDK版本使用 ​ 进入官网:点此进入Oracle官网 ​ 选择需要的对应版本下载,我选择的是mac OS的11版本jdk-11.0.19_macos-x64_bin

    2024年02月16日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包