分享

jdk8到jdk17新特性整理

 笑笑兔 2023-08-31 发布于天津

 一、Java平台模块化系统

jdk9最亮眼的特性就是java平台模块化系统。与jdk函数式编程和lambda表达式存在本质区别。

1、什么是模块化

java模块化就是将目前多个包(package)组成一个封装体,同时也存在具体实例。

模块化三个原则:强封装、定义良好接口、显示依赖。

强封装性:一个模块可以选择性的对其他模块隐藏部分实现细节。

定义良好的接口:一个模块只有封装是不够的,还要通过对外暴露接口与其他模块交互。因此,暴露的接口必须有良好的定义。

显示依赖:一个模块通常需要协同其他模块一起工作,该模块必须显示的依赖其他模块 ,这些依赖关系同时也是模块定义的一部分。

二、优化垃圾回收

JDK11中最明显的新特性就是ZGC垃圾回收器。作为实验性功能,ZGC的特点包括:

  • GC停顿时间不会超过10ms。

  • 停顿时间不会随着堆的大小,或者活跃对象的大小而增加;

  • 相对于G1垃圾回收器而言,吞吐量降低不超过15%;

  • 支持Linux/x64、window和mac平台;

  • 支持8MB~16TB级别的堆回收。

同时根据openJDK官方的性能测试数据显示(JEP333),ZGC的表现非常的出色:

  • 在仅关注吞吐量指标下,ZGC超过了G1;

  • 在最大延迟不超过某个设定值(10到100ms)下关注吞吐量,ZGC较G1性能更加突出。

  • 在仅关注低延迟指标下,ZGC的性能高出G1将近两个数量级。99.9th仅为G1的百分之一

三、优化诊断监控

jdk9之前日志

2014-12-10T11:13:09.597+0800: 66955.317: [GC concurrent-root-region-scan-start]
2014-12-10T11:13:09.597+0800: 66955.318: Total time for which application threads were stopped: 0.0655753 seconds
2014-12-10T11:13:09.610+0800: 66955.330: Application time: 0.0127071 seconds
2014-12-10T11:13:09.614+0800: 66955.335: Total time for which application threads were stopped: 0.0043882 seconds
2014-12-10T11:13:09.625+0800: 66955.346: [GC concurrent-root-region-scan-end, 0.0281351 secs]
2014-12-10T11:13:09.625+0800: 66955.346: [GC concurrent-mark-start]
2014-12-10T11:13:09.645+0800: 66955.365: Application time: 0.0306801 seconds
2014-12-10T11:13:09.651+0800: 66955.371: Total time for which application threads were stopped: 0.0061326 seconds
2014-12-10T11:13:10.212+0800: 66955.933: [GC concurrent-mark-end, 0.5871129 secs]
2014-12-10T11:13:10.212+0800: 66955.933: Application time: 0.5613792 seconds
2014-12-10T11:13:10.215+0800: 66955.935: [GC remark 66955.936: [GC ref-proc, 0.0235275 secs], 0.0320865 secs]

jdk9之后日志

[2021-02-09T21:12:50.870+0800][258][info][gc] Using G1
[2021-02-09T21:12:51.751+0800][365][info][gc] GC(0) Pause Young (Concurrent Start) (Metadata GC Threshold) 60M->5M(4096M) 7.689ms
[2021-02-09T21:12:51.751+0800][283][info][gc] GC(1) Concurrent Cycle
[2021-02-09T21:12:51.755+0800][365][info][gc] GC(1) Pause Remark 13M->13M(4096M) 0.959ms
[2021-02-09T21:12:51.756+0800][365][info][gc] GC(1) Pause Cleanup 13M->13M(4096M) 0.127ms
[2021-02-09T21:12:51.758+0800][283][info][gc] GC(1) Concurrent Cycle 7.208ms
[2021-02-09T21:12:53.232+0800][365][info][gc] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 197M->15M(4096M) 17.975ms
[2021-02-09T21:12:53.952+0800][365][info][gc] GC(3) Pause Young (Concurrent Start) (GCLocker Initiated GC) 114M->17M(4096M) 15.383ms
[2021-02-09T21:12:53.952+0800][283][info][gc] GC(4) Concurrent Cycle

四、优雅语法、方法

4.1、集合工厂

list、set和map接口,新的静态工厂方法可以创建不可变集合

// 创建只有一个值的可读list,底层不使用数组
static <E> List<E> of(E e1) {
   return new ImmutableCollections.List12<>(e1);
}
// 创建有多个值的可读list,底层使用数组
static <E> List<E> of(E e1, E e2, E e3) {
   return new ImmutableCollections.List12<>(e1, e2,e3);
}
// 创建单例长度为0的Set结合
static <E> Set<E> of() {
   return ImmutableCollections.emptySet();
}
static <E> Set<E> of(E e1) {
   return new ImmutableCollections.Set12<>(e1);
}

4.2、接口私有化

java8接口可以有默认方法。java9之后,接口内实现私有方法

public interface HelloService {
    public void sayHello();
    // 默认方法
    default void saySomething(){
        syaEngHello();
        sayHello();
    };
    // 私有方法
    private void syaEngHello(){
        System.out.println("Hello!");
    }
}

4.3、改进StreamApi

// 循环直到第一个满足条件后停止
default Stream takeWhile(Predicate predicate);
// 循环直到第一个满足条件后开始
default Stream dropWhile(Predicate predicate);
// 根据表达式生成迭代器
static  Stream iterate(T seed, Predicate hasNext, UnaryOperator next);
// 使用空值创建空的Stream,避免空指针
static  Stream ofNullable(T t);

4.4、局部类型推断

jdk10推出了局部类型推断,使用var作为局部类型。

public static void main(String[] args) throws Exception {
    var lists = List.of("a", "b", "c");
    for (var word : lists) {
        System.out.println(word);
    }
    var num = 10;
    System.out.println(num);
    num = "10";//编译报错
}

4.5、标准java Http Client

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("http://openjdk./"))
      .build();
client.sendAsync(request, BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenAccept(System.out::println)
      .join();

4.6、优雅instance of 语法

以前代码

if (obj instanceof String) {
    String s = (String) obj;    // grr...
    ...
}

jdk16中,使用模式匹配思想改进

if (obj instanceof String s) {// obj是否为String类型,如果是创建临时变量s
    // Let pattern matching do the work!
    ...
}

合理使用,代码效果

// 优化使用前
public final boolean equals(Object o) {
    if (!(o instanceof Point))
        return false;
    Point other = (Point) o;
    return x == other.x
        && y == other.y;
}
// 优化使用后:
public final boolean equals(Object o) {
    return (o instanceof Point other)
        && x == other.x
        && y == other.y;
}

4.7、优雅的Switch用法

// 之前
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
// 之后
switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

将switch语句当成表达式

T result = switch (arg) {
    case L1 -> e1;
    case L2 -> e2;
    default -> e3;
};

static void howMany(int k) {
    System.out.println(
        switch (k) {
            case  1 -> "one";
            case  2 -> "two";
            default -> "many";
        }
    );
}

五、Java Flow Api

Reactive Streams是一套非阻塞背压的异步数据流处理规范。从Java9开始,Java原生支持Reactive Streams编程规范。

五、字符串压缩

符串是我们日常编程中使用最频繁的基本数据类型之一。目前,字符串类底层都使用了一个字符数组来实现,每个字符使用2个字节(16位)空间。实际上,大量的字符都属于Latin-1字符范围内,我们只需要一个字节就能存储这些数据,因此这里有巨大的可压缩空间;

  


总结

从JDK9到JDK17,我们大致有个了解。大量的新特性,意味着更优秀的性能及更高效的开发方法,应该积极主动的尝试高版本JDK。本人能力有限,可能出现理解偏差、漏洞,望大家指正!

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多