一、接口的私有方法

  Java 8中规定接口中的方法除了抽象方法之外, 还可以定义静态方法和默认的方法。 一定程度上, 扩展了接口的功能, 此时的接口更像是一个抽象类。

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

  案例:

  MyInterface:

 1 public interface MyInterface {
 2     //如下的三个方法的权限修饰符都是public
 3     void methodAbstract();
 4 
 5     static void methodStatic(){
 6         System.out.println("我是接口中的静态方法");
 7     }
 8 
 9     default void methodDefault(){
10         System.out.println("我是接口中的默认方法");
11 
12         methodPrivate();
13     }
14     //jdk 9中允许接口中定义私有的方法
15     private void methodPrivate(){
16         System.out.println("我是接口中的私有方法");
17     }
18 }

 

  MyInterfaceImple:

 1 public class MyInterfaceImpl implements MyInterface {
 2 
 3 
 4     @Override
 5     public void methodAbstract() {
 6 
 7     }
 8 
 9     //@Override
10     public void methodDefault() {
11         System.out.println("实现类重写了接口中的默认方法");
12     }
13 
14     public static void main(String[] args) {
15         //接口中的静态方法只能由接口自己调用
16         MyInterface.methodStatic();
17         //接口的实现类不能调用接口的静态方法
18         //MyInterfaceImpl.methodStatic();
19 
20         MyInterfaceImpl impl = new MyInterfaceImpl();
21         impl.methodDefault();
22         //接口的私有方法,不能在接口外部调用
23         //impl.methodPrivate();
24     }
25 }

 

 

二、钻石操作符使用升级

    我们将能够与匿名实现类共同使用钻石操作符(diamond operator) 在Java 8 中如下的操作是会报错的:
    

    编译报错信息: Cannot use “<>” with anonymous inner classes.

 

    Java 9中如下操作可以正常执行通过:

 1     //java9特性五:钻石操作符的升级
 2     @Test
 3     public void test2() {
 4         //钻石操作符与匿名内部类在java 8中不能共存。在java9可以。
 5         Comparator<Object> com = new Comparator<>() {
 6             @Override
 7             public int compare(Object o1, Object o2) {
 8                 return 0;
 9             }
10         };
11 
12         //jdk7中的新特性:类型推断
13         ArrayList<String> list = new ArrayList<>();
14     }

 

三、try语句

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

    Java8 之前:

 1         //java 8之前的资源关闭的操作
 2         InputStreamReader reader = null;
 3         try {
 4             reader = new InputStreamReader(System.in);
 5             char[] cbuf = new char[20];
 6             int len;
 7             if((len = reader.read(cbuf) )!= -1){
 8                 String str = new String(cbuf,0,len);
 9                 System.out.println(str);
10             }
11         } catch (IOException e) {
12             e.printStackTrace();
13         } finally {
14             if(reader != null){
15                 try {
16                     reader.close();
17                 } catch (IOException e) {
18                     e.printStackTrace();
19                 }
20 
21             }
22         }

 

    Java8 中:

 1         //java 8中资源关闭操作: Java 8 中,可以实现资源的自动关闭
 2         //要求自动关闭的资源的实例化必须放在try的一对小括号中
 3         try(InputStreamReader reader = new InputStreamReader(System.in)){
 4             char[] cbuf = new char[20];
 5             int len;
 6             if((len = reader.read(cbuf) )!= -1){
 7                 String str = new String(cbuf,0,len);
 8                 System.out.println(str);
 9             }
10         } catch (IOException e) {
11             e.printStackTrace();
12         }

 

  

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

 1      //java9中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外。
 2        //此时的资源属性是常量,声明为final的,不可修改,具体读写操作省略
 3         InputStreamReader reader = new InputStreamReader(System.in);
 4        OutputStreamWriter writer = new OutputStreamWriter(System.out);
 5         try (reader, writer) {
 6 
 7             char[] cbuf = new char[20];
 8             int len;
 9             if((len = reader.read(cbuf) )!= -1){
10                 String str = new String(cbuf,0,len);
11                 System.out.println(str);
12             }
13 
14             //reader = null;
15         } catch (IOException e) {
16             e.printStackTrace();
17         }

 

 

四、String存储结构变更

    

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

    

 

    那StringBuffer 和 StringBuilder 是否仍无动于衷呢?

    

 

五、集合工厂方法:快速创建只读集合

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

 1     //java8中的写法:
 2     @Test
 3     public void test1() {
 4         List<String> namesList = new ArrayList<>();
 5         namesList.add("Joe");
 6         namesList.add("Bob");
 7         namesList.add("Bill");
 8         //返回的namesList是一个只读的集合
 9         namesList = Collections.unmodifiableList(namesList);
10         namesList.add("Tom");
11         System.out.println(namesList);
12     }

 

  缺点:写下了多行,即不能表达单个表达式。

 1     @Test
 2     public void test2() {
 3         List<String> list = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
 4         Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
 5         // 如下操作不适用于jdk 8 及之前版本,适用于jdk 9
 6         Map<String, Integer> map = Collections.unmodifiableMap(new HashMap<>() {
 7             {
 8                 put("a", 1);
 9                 put("b", 2);
10                 put("c", 3);
11             }
12         });
13         map.forEach((k, v) -> System.out.println(k + ":" + v));
14     }

 

  调用 Arrays 的 asList() 方法也可以获取一个只读集合:

1     @Test
2     public void test3() {
3         //此时得到的集合list也是一个只读集合。
4         List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
5         //报异常
6         list.add(6);
7     }

 

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

  Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。

  List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素:

  使用前提:当集合中存储的元素的个数已经确定了,不在改变时使用

 

List firsnamesList = List.of("Joe","Bob","Bill");

  

  调用集合中静态方法of(), 可以将不同数量的参数传输到此工厂方法中。 此功能可用于Set和List, 也可用于Map的类似形式。 此时得到的集合, 是不可变的:在
创建后, 继续添加元素到这些集合会导致 “UnsupportedOperationException” 。
  由于Java 8中接口方法的实现, 可以直接在List, Set和Map的接口内定义这些方法,便于调用。

  

 

  Java9 新增方法:

 1     //java9新特性八:集合工厂方法:创建只读集合
 2     @Test
 3     public void test4() {
 4         List<Integer> list1 = List.of(1, 2, 3, 4, 5);
 5         //不能添加
 6         //list1.add(6);
 7         System.out.println(list1);
 8 
 9         Set<Integer> set1 = Set.of(23, 3, 54, 65, 43, 76, 87, 34, 46);
10         //不能添加
11         //set1.add(4);
12         System.out.println(set1);
13 
14         Map<String, Integer> map1 = Map.of("Tom", 23, "Jerry", 54, "HanMeimei", 12);
15         //不能添加
16         //map1.put("Lilei",34);
17 
18         System.out.println(map1);
19 
20         Map<String, Integer> map2 = Map.ofEntries(Map.entry("Tom", 34), Map.entry("Jerry", 21));
21         //map2.put("Lilei",34);
22         System.out.println(map2);
23     }

 

  Demo2:

 1  public static void main(String[] args) {
 2         List<String> list = List.of("a", "b", "a", "c", "d");
 3         System.out.println(list);//[a, b, a, c, d]
 4         //list.add("w");//UnsupportedOperationException:不支持操作异常
 5 
 6         //Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素
 7         Set<String> set = Set.of("a", "b", "c", "d");
 8         System.out.println(set);
 9         //set.add("w");//UnsupportedOperationException:不支持操作异常
10 
11         //Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20,"张三",19);////IllegalArgumentException:非法参数异常,有重复的元素
12         Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);
13         System.out.println(map);//{王五=20, 李四=19, 张三=18}
14         //map.put("赵四",30);//UnsupportedOperationException:不支持操作异常
15     }

 

 

  注意:  

    1. of方法只适用于 List接口,Set接口,Map接口,不适用于接接口的实现类;

    2. of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常;

    3. Set 接口和 Map 接口在调用 of 方法的时候,不能有重复的元素,否则会抛出异常;

 

六、InputStream 加强

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

 1     //java9新特性九:InputStream的新方法:tranferTo()
 2     @Test
 3     public void test5() {
 4         ClassLoader cl = this.getClass().getClassLoader();
 5         try (InputStream is = cl.getResourceAsStream("hello.txt");
 6              OutputStream os = new FileOutputStream("src\\hello1.txt")) {
 7             is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
 8         } catch (IOException e) {
 9             e.printStackTrace();
10         }
11     }

 

七、增强的 Stream API

  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 返回从开头开始的尽量多的元素

1     //takeWhile 返回从开头开始的按照指定规则尽量多的元素
2     @Test
3     public void test() {
4         List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88);
5         list.stream().takeWhile(x -> x < 50).forEach(System.out::println); //45,43
6         System.out.println();
7         list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
8         list.stream().takeWhile(x -> x < 5).forEach(System.out::println); //1,2,3,4
9     }

 

  2、dropWhile() 的使用

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

1      //dropWhile():与 takeWhile 相反,返回剩余的元素。
2     @Test
3     public void test() {
4         List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88);
5         list.stream().dropWhile(x -> x < 50).forEach(System.out::println); //76,87,42,77,90,73,67,88
6         System.out.println();
7         list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
8         list.stream().dropWhile(x -> x < 5).forEach(System.out::println); //5,6,7,8
9     }

 

  3、ofNullable() 的使用

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

 1     @Test
 2     public void test1(){
 3         // of()参数不能存储单个null值。否则,报异常,报NullPointerException
 4          Stream<Object> stream1 = Stream.of(null);
 5          System.out.println(stream1.count());
 6 
 7 
 8         // of()参数中的多个元素,可以包含null值,不报异常,允许通过,
 9         Stream<String> stringStream = Stream.of("AA", "BB", null);
10         System.out.println(stringStream.count());// 3
11 
12 
13         // 不报异常,允许通过
14         List<String> list = new ArrayList<>();
15         list.add("AA");
16         list.add(null);
17         System.out.println(list.stream().count());// 2
18 
19 
20         // ofNullable():允许值为null,ofNullable():形参变量是可以为null值的单个元素
21         Stream<Object> stream2 = Stream.ofNullable(null);
22         System.out.println(stream2.count());// 0
23         Stream<String> stream = Stream.ofNullable("hello world");
24         System.out.println(stream.count());// 1
25     }

 

  4、iterate() 重载的使用

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

 

1     @Test
2     public void test3(){
3         //原来的控制终止方式
4         Stream.iterate(0,x -> x + 1).limit(10).forEach(System.out::println);
5 
6 
7         //java9中新增的重载的方法
8         Stream.iterate(0,x -> x < 100,x -> x + 1).forEach(System.out::println);
9     }

 

八、Optional 获取 Stream 的方法

  Optional 类提供了 Stream() 的使用:

 1     //java9新特性十一:Optional提供了新的方法stream()
 2     @Test
 3     public void test4(){
 4         List<String> list = new ArrayList<>();
 5         list.add("Tom");
 6         list.add("Jerry");
 7         list.add("Tim");
 8 
 9         Optional<List<String>> optional = Optional.ofNullable(list);
10         Stream<List<String>> stream = optional.stream();
11         //long count = stream.count();
12         //System.out.println(count);
13         stream.flatMap(x -> x.stream()).forEach(System.out::println);
14 
15     }

 

九、JavaScript 引擎升级:Nashorn

  Nashorn 项目在 JDK 9 中得到改进, 它为 Java 提供轻量级的 Javascript 运行时。Nashorn 项目跟随 Netscape 的 Rhino 项目, 目的是为了在 Java 中实现一个高性能但轻量级的 Javascript 运行时。 Nashorn 项目使得 Java 应用能够嵌入Javascript。 它在 JDK 8 中为 Java 提供一个 Javascript 引擎。
  JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。 这个 API 使得IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类, 就能够分析ECMAScript 代码。

  

 

 

posted on 2021-07-28 21:52  格物致知_Tony  阅读(370)  评论(0)    收藏  举报