JDK版本特性(三)JDK9

发布时间 2023-12-18 13:56:08作者: Tod4

JDK9新特性


概述

​ java9提供了近150项新功能,包括:

  • 模块化系统
  • jShell命令
  • 多版本兼容jar包
  • 接口的私有方法
  • 钻石操作符的升级使用
  • 语法改进:try
  • String存储结构
  • 集合特性:of()
  • 增强streamAPI
  • 全新HTTP客户端API
  • Deprecated的相关API
  • java动态编译器
  • 。。。

1 目录结构改变

​ 将原来的jre打散到了现有目录中

image-20231128201609311 image-20231128201634223

2 模块化系统

​ 类似于javaScript ES6的模块化,需要在每个module下面创建一个module-info.java文件,使用exports暴露具体暴露的类,然后在另一个module下的module-info.java中引入该module,这样一个module就能够访问其他module的公共类了

​ 引入模块化的原因:

image-20231128205048545

3 jShell

​ 像python、scala的交互式编程环境REPL一样,提供java编程环境

image-20231128212540877

4 接口声明私有方法

  • 接口中的方法默认都是public abstract

  • 在jdk8中,除了默认的抽象方法,还能够写入静态方法默认方法

    public interface TestInterface {
    
        private void methodPrivate() {
            System.out.println("private method");
        }
    
        static void methodStatic() {
            System.out.println("static method");
        }
    
        public default void methodDefault() {
            System.out.println("default method");
        }
    
        void method();
    }
    

    1 default在这里是一个关键字,用于修饰默认方法,而不是访问权限(默认访问权限没有关键字

    2 接口的静态方法只能够由接口调用

    3 默认方法对应着abstract,抽象方法必须被重写而默认方法不需要,这也是jdk9里面不需要重写所有的接口方法的原因

    public class TestInterfaceImpl implements TestInterface{
    
        @Override
        public void methodDefault() {
            TestInterface.super.methodDefault();
        }
    
        @Override
        public void method() {
    
        }
    }
    
    
  • 在jdk9中,引入了私有方法

    public interface TestInterface {
    
        private void methodPrivate() {
            System.out.println("private method");
        }
    
        static void methodStatic() {
            System.out.println("static method");
        }
    
        public default void methodDefault() {
            System.out.println("default method");
        }
    
        void method();
    }
    

5 钻石操作符的编译优化

  • 在jdk9后,匿名内部类可以和钻石操作符共存了

            Comparator<Object> c = new Comparator<>() {
                @Override
                public int compare(Object o1, Object o2) {
                    return 0;
                }
            };
    
  • 也就是匿名内部类能够通过前面的声明在编译期间推断出类型,类似于jdk7中的类型推断

    		ArrayList<Integer> list = new ArrayList<>();
    

6 try with resource

  • 常用的资源关闭方式:

        public static void main(String[] args)  {
            InputStreamReader reader = null;
            try {
                reader = new InputStreamReader(System.in);
                char[] buf = new char[20];
                int len = 0;
                while((len = reader.read(buf)) != -1) {
                    var str = new String(buf, 0, len);
                    System.out.println(str);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    
  • jdk8后,可以实现资源自动关闭,但是必须在try中进行资源的初始化

    public class TryWithResourceTest {
        public static void main(String[] args)  {
            try(InputStreamReader reader = new InputStreamReader(System.in)) {
                char[] buf = new char[20];
                int len = 0;
                while((len = reader.read(buf)) != -1) {
                    var str = new String(buf, 0, len);
                    System.out.println(str);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
  • jdk9开始,不必在括号中进行初始化,但是要求reader为final,不能被修改

    public class TryWithResourceTest {
        public static void main(String[] args)  {
            InputStreamReader reader = new InputStreamReader(System.in);
            try(reader) {
                char[] buf = new char[20];
                int len = 0;
                while((len = reader.read(buf)) != -1) {
                    var str = new String(buf, 0, len);
                    System.out.println(str);
                }
    
    //            reader = null; 不能修改
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    

7 String底层存储结构修改

  • 由以前的char[]变为了byte[]
  • 原因是一个字符占两个字节,很多中文拉丁文一个字符3个字节浪费空间

8 集合工程创建只读集合

  • 创建一个只读、不可修改的集合,必须先创建并添加元素到一个集合:

    public class ReadCollectionTest {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("1");
            list.add("2");
            list.add("3");
    
            list = Collections.unmodifiableList(list);
    //        list.add("2");
            System.out.println(list);
        }
    }
    
  • 上面还可以写到匿名内部类中:

            Map<Object, Object> map1 = Collections.unmodifiableMap(new HashMap<>() {
                {
                    put("1", 1);
                }
            });
    
  • jdk9中提供集合工厂方法可以直接创建只读集合

    public class ReadCollectionTest {
        public static void main(String[] args) {
            List<String> list;
            list = List.of("1", "2", "3");
            // unsupportedOperationException
    //        list.add("2");
            System.out.println(list);
    
            Map<String, Integer> stringIntegerMap = Map.of("1", 1, "2", 2);
            System.out.println(stringIntegerMap);
        }
    }
    
  • map也可以使用Map.ofEntries()

    Map<String, Integer> map2 = Map.ofEntries(Map.entry("1", 1));
    

9 InputStream加强

  • java8中StreamAPI可以实现快速运算和数据并行计算

  • jdk9添加了四个新方法:

    • dropWhile

              var intStream
                      = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
              // 符合条件的留下,直到不符合停止
              var takeStream
                      = intStream.takeWhile(x -> x < 5);
              takeStream.forEach(System.out::print);
      
              System.out.println();
      
    • takeWhile

              // 符合条件删除,直到不符合条件
              var intStream2
                      = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
              var dropStream
                      = intStream2.dropWhile(x -> x < 5);
              dropStream.forEach(System.out::print);
      
    • ofNullAble

      在jdk8中,不允许单个为null的stream但是可以多个包含null的:

              var stream = Stream.of(null, null);
      //        null
      //        null
              stream.forEach(System.out::println);
      
              // NullPointerException
              var stream2 = Stream.of(null);
              stream2.forEach(System.out::println);
      

      类似于Optional的ofNullable,jdk9中也可以:

              var stream3 = Stream.ofNullable(null);
              stream3.forEach(System.out::println);
      
    • 重载Stream.iterator():可以自行添加终止条件(通过一个Predicate接口实现)

          public static void main(String[] args) {
              var stream = Stream.iterate(0,
                      x -> x < 10,
                      x -> x + 1);
              // 0123456789
              stream.forEach(System.out::print);
          }
      

10 Optional Stream

  • Optional获得的Stream是封装元素作为的一个整体Stream

  • 如果想要获取元素内部的元素流,需要使用flatmap进行展开

    /**
     * @description: some desc
     * @author: whiteStream
     * @email: 819574539@qq.com
     * @date: 2023/12/2 15:43
     */
    public class StreamTest {
        public static void main(String[] args) {
            var list = List.of("aaa", "bbb", "ccc");
            var optional = Optional.ofNullable(list);
            
            // Stream<List<String>>
            var stream = optional.stream();
            // 1
            System.out.println(stream.count());
    
            Stream<String> stringStream
                    = optional.stream().flatMap(x -> x.stream());
            // 3
            System.out.println(stringStream.count());
        }
    
    }
    

11 JavaScript引擎:Nashorm

​ 已经deprecated