JDK9-17新特性

一、JDK9新特性

1.概述

jdk9的新特性主要包括:

1.模块化系统(Module System):这是Java9最大的特性,它提供了类似于OSGI框架的功能,模块之间存在相互依存的依赖关系,可以导出一个公共的API,并且隐藏实现的细节。Java提供该功能的主要动机在于,减少内存的开销。

2.Jshell和Jlink:JShell是Java9中新增的交互式Java编程环境,类似于Python的交互式环境。它允许开发者在命令行中快速编写和测试Java代码。Jlink是Java9中新增的工具,用于生成自定义的Java运行时映像,可以包含或排除特定的模块。

3.不可变集合类工厂方法:Java9新增了一些不可变集合类工厂方法,这些方法可以更方便的创建不可变集合。

4.接口中的私有方法:在Java9中,接口可以包含私有方法,这使得接口的实现更加灵活。

5.try-with-resources改进:java9对try-with-resources进行了改进,使得能够更好的处理异常和资源关闭。

6.平台日志API和服务:Java9提供了新的平台日志API和服务,这使得开发者可以更加方便的记录日志。

7.垃圾回收器:Java9新增了Shenandoah垃圾回收器,这是一种新的垃圾回收器,旨在提供更高效的垃圾回收。

2、模块化系统

JDK1.8之前:Jar+package+class|interface

JDK1.8之后:Jar+module+package+class|interface

 

实现目标:

1.模块化的主要目的在于减少内存的开销

2.只需必要的模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护

3.改进Java SE平台,使其可以适应不同大小的计算设备

4.改进其安全性,可维护性,提高性能 

注意:导入外部的junit模块并使用,必须将当前模块导出。

3.接口私有化

 在Java 9中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为private的了,此时方法将不会成为你对外暴露的API的一部分。

package top.psjj.demo1;

public interface JDK9Demo4 {
    //接口默认都是共有静态常量
    public static final int NUM = 10;
    //接口默认方法都是抽象方法
    public abstract void method1();

    //jdk8接口可以有静态方法
    public static void method2(){
        System.out.println("接口中的静态方法");
    }
    //jdk8接口可以有默认方法
    public default void method3(){
        System.out.println("接口中的默认方法");
    }
    //jdk9接口可以有私有方法
    private void method4(){
        System.out.println("接口中的私有方法");
    }
}

4.钻石操作符使用升级 

 在jdk8中,如下代码是报错的

Comparator<Object> com = new Comparator<>() {
    @Override
    public int compare(Object o1, Object o2) {
        return 0;
    }
};

<>必须写类型。

而在jdk9中,上述代码就不报错,这是对<>钻石运算符的一个升级。

5.try语句

 

Java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。如下例所示:

 Java 9 中,用资源语句编写try将更容易,我们可以在try子句中使用已经初始化过的资源,此时的资源是final的

 

6.String存储结构变更 

 

结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。

7.只读集合of()

 要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。

缺点:我们一下写了五行。即:它不能表达为单个表达式。

Java 9因此引入了方便的方法,这使得类似的事情更容易表达。

 

public class Demo5 {
    public static final List<String> list = List.of("type_weixin","type_zhifubao","type_yinhangka");
    public static void main(String[] args) {
        //jdk8以前创建只读集合
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        Collection<String> list2 = Collections.unmodifiableCollection(list);
//        list2.add("赵六");
//        System.out.println(list2);
        //jdk9创建只读集合
        List<String> list3 = List.of("张三", "李四", "王五");
        System.out.println(list3);
        Set<String> set1 = Set.of("AA", "BB", "CC");
        System.out.println(set1);
        Map<String, String> map = Map.of("k1", "v1", "k2", "v2");
        System.out.println(map);
    }
}

8.InputStream增强

InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到 OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例。

9.增强的StreamAPI

 

  • Java 的 Steam API 是java标准库最好的改进之一,让开发者能够快速运算,从而能够有效的利用数据并行计算。Java 8 提供的 Steam 能够利用多核架构实现声明式的数据处理。

  • 在 Java 9 中,Stream API 变得更好,Stream 接口中添加了 4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。

  • 除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。现在可以通过 Optional 的新方法 stream() 将一个 Optional 对象转换为一个(可能是空的) Stream 对象。

1.takeWhile()的使用 

 用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的Stream 中,takeWhile 返回从开头开始的尽量多的元素

public static void main(String[] args) throws Exception {
    List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
    list.stream().takeWhile(t->t<40).forEach(System.out::println);

    List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
    list2.stream().takeWhile(t->t<7).forEach(System.out::println);
}

2.dropWhile()的使用 

dropWhile 的行为与 takeWhile 相反,返回剩余的元素

public static void main(String[] args) throws Exception {
    List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
    list.stream().dropWhile(t->t<40).forEach(System.out::println);

    List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
    list2.stream().dropWhile(t->t<7).forEach(System.out::println);
}

3.ofNullable()的使用

Java 8 中 Stream 不能完全为null,否则会报空指针异常。而 Java 9 中的 ofNullable 方法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空Stream。

 

public static void main(String[] args) throws Exception {
    //允许通过
    Stream<String> streams = Stream.of("AA","BB",null);
    System.out.println(streams.count());
    //不允许通过
    /*Stream<Object> stream2 = Stream.of(null);
        System.out.println(stream2.count());*/
    //允许通过
    Stream<Object> stream2 = Stream.ofNullable(null);
    System.out.println(stream2.count());
}

4.iterate()重载的使用

 这个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。

public static void main(String[] args) throws Exception {
    //原始方式
    Stream.iterate(1,i->i+1).limit(50).forEach(System.out::println);
    //增强方式
    Stream.iterate(1,i->i<60,i->i+1).forEach(System.out::println);
}

10.Optional类中stream()使用

 

public static void main(String[] args) throws Exception {
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    list.add("王五");
    list.add("赵六");
    Optional<List<String>> optional = Optional.ofNullable(list);
    optional.stream().flatMap(x->x.stream()).limit(2).forEach(System.out::println);

    list.stream().limit(2).forEach(System.out::println);
}

二、JDK10新特性 

1.局部变量类型推断 

 

 在局部变量中使用时,如下情况不适用:

 

注意:

  • var 不是一个关键字:你不需要担心变量名或方法名会与 var发生冲突,因为 var实际上并不是一个关键字,而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。除此之外,它就是一个普通合法的标识符。也就是说,除了不能用它作为类名,其他的都可以,但极少人会用它作为类名。

  • 这不是JavaScript:首先我要说明的是,var并不会改变Java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。下面是使用 IntelliJ(实际上是 Fernflower的反编译器)反编译器反编译出的代码

2.新增不可变集合方法(只读) 

 自 Java 9 开始,Jdk 里面为集合(List / Set / Map)都添加了 of (jdk9新增)和copyOf (jdk10新增)方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。

 

public static void main(String[] args) throws Exception {
    //示例1
    var list1 = List.of("AA","BB","CC");
    var list2 = List.copyOf(list1);
    System.out.println(list1==list2);//true
    //示例2
    var list3 = new ArrayList<String>();
    list3.add("AA");
    list3.add("BB");
    List<String> list4 = List.copyOf(list3);
    System.out.println(list3==list4); //false
}

 从 源 码 分 析 , 可 以 看 出 copyOf 方 法 会 先 判 断 来 源 集 合 是 不 是AbstractImmutableList 类型的,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。

示例2因为用的 new 创建的集合,不属于不可变 AbstractImmutableList 类的子类,所以 copyOf 方法又创建了一个新的实例,所以为false。

注意:使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。

上面演示了 List 的 of 和 copyOf 方法,Set 和 Map 接口都有。

三、JDK11新特性

1.增加ZGC垃圾回收器

 GC是java主要优势之一。 然而, 当GC停顿太长, 就会开始影响应用的响应时间。消除或者减少GC停顿时长, java将对更广泛的应用场景是一个更有吸引力的平台。此外, 现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存, 并且无需长时间的GC暂停时间。

优势:

  • GC暂停时间不会超过10ms

  • 既能处理几百兆的小堆, 也能处理几个T的大堆(OMG)

  • 和G1相比, 应用吞吐能力不会下降超过15%

  • 为未来的GC功能和利用colord指针以及Load barriers优化奠定基础

  • 初始只支持64位系统

2.Optional加强 

 Optional 也增加了几个非常酷的方法,现在可以很方便的将一个 Optional 转换成一个 Stream, 或者当一个空 Optional 时给它一个替代的。

 3.新增HTTP客户端API

  • HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。 HTTP/2允许服务器“push”数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据。

  • 这是 Java 9 开始引入的一个处理 HTTP 请求的的 HTTP Client API,该API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你可以在java.net 包中找到这个 API。

  • 它 将 替 代 仅 适 用 于 blocking 模 式 的 HttpURLConnection(HttpURLConnection是在HTTP 1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket 和 HTTP/2的支持

public static void main(String[] args) throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request =
        HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
    HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
    HttpResponse<String> response = client.send(request, responseBodyHandler);
    String body = response.body();
    System.out.println(body);
}

 四、JDK14新特性

 改进的NullPointerExceptions,jdk14以前空指针异常

public static void main(String[] args) throws Exception {
    String str = null;
    System.out.println(str.equals("AA"));
}

异常

jdk14以后的空指针异常

 

五、JDK16新特性 

在Java16中正式发布Switch升级,其目的是为了解决switch语句的一些不规则性成为障碍

  • 比如case标签之间的默认控制行为

  • case块中的默认范围

  • 无意义的break语句。

 jdk16以前switch结构用法

public static void main(String[] args) {
    int level = new Random().nextInt(4);
    String strLevel;
    switch (level){
        case 1:
            strLevel = "优秀";
            break;
        case 2:
            strLevel = "良好";
            break;
        default:
            strLevel = "一般";
            break;
    }
    System.out.println(strLevel);
}

 jdk16对应用法

 

public static void main(String[] args) {
    int level = new Random().nextInt(4);
    String strLevel;
    switch (level){
        case 1 -> strLevel="优秀";
        case 2 -> strLevel="良好";
        default -> strLevel="一般";
    }
    System.out.println(strLevel);
}

public static void main(String[] args) {
    int level = new Random().nextInt(4);
    String strLevel = switch (level){
        case 1-> "优秀";
        case 2-> "良好";
        default -> "一般";
    };
    System.out.println(strLevel);
}

public static void main(String[] args) {
    int level = new Random().nextInt(12);
    String jiJi = null;
    switch (level){
        case 3,4,5 -> jiJi =  "春天";
        case 6,7,8 -> jiJi =  "夏天";
        case 9,10,11 -> jiJi =  "秋天";
        case 12,1,2 -> jiJi = "冬天";
    };
    System.out.println(jiJi);
}

除此之外还有一个场景:

public static void main(String[] args) {
    int level = new Random().nextInt(4);
    String strLeave = switch (level){
        case 1 -> {
            System.out.println("优秀");
            yield "优秀";
        }
        default -> "进步空间很大";
    };
    System.out.println(strLeave);
}

对应编译后的代码

public static void main(String[] args) {
    int level = (new Random()).nextInt(4);
    String var10000;
    switch (level) {
        case 1:
            System.out.println("优秀");
            var10000 = "优秀";
            break;
        default:
            var10000 = "进步空间很大";
    }

    String strLeave = var10000;
    System.out.println(strLeave);
}

六、JDK15新特性补充 

 jdk15提供text block 功能,解决字符串多行换行问题;示例如下

public static void main(String[] args) {
    //jdk15增加文本块
    String str = """
        hello
        world
        hahaha
        """;
        System.out.println(str);
}

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值