学习笔记 : 详解JDK 9中的新特性 由于 JDK9 中下面两个特性很重要,所有小哥我就单独分开写啦~
接口的私有方法 Java 8 中规定接口中的方法除了抽象方法之外,还可以定义静态和默认的方法. 一定程度上扩展了接口的功能,此时的接口更像是一个抽象类. 而在 Java 9 中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为 private 的了,此时方法将不会成为你对外暴露的 API 的一部分,话说这个语法的改进不应该在 Java 8 中就施行的嘛~ 示例程序如下 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package pers.huangyuhui.jdk9;import org.junit.Test;interface MyInterface { public default void defaultMethod () { privateMethod(); System.out.println("this is default method" ); } public static void staticMethod () { System.out.println("this is static method" ); } private void privateMethod () { System.out.println("this is private method" ); } } public class Grammar implements MyInterface { @Test public void test () { MyInterface.staticMethod(); new Grammar().defaultMethod(); } }
程序运行结果如下所示 :
1 2 3 this is static method this is private method this is default method
钻石操作符的使用升级 与匿名实现类共同使用钻石操作符( diamond operator )在 Java 8 中如下的操作是会报错的,编译报错信息 : Cannot use "<>" with anonymous inner classes
,在IDEA中将 Language level 调成 Java 9 即可解决编译错误啦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Test public void testComparator () { Comparator<Integer> comparator = new Comparator<>() { @Override public int compare (Integer o1, Integer o2) { return Integer.compare(o1, o2); } }; System.out.println(comparator.compare(1 , 2 )); } @Test public void testComparatorWithLambda () { Comparator<Integer> comparator = (o1, o2) -> Integer.compare(o1, o2); System.out.println(comparator.compare(1 , 2 )); } @Test public void testComparatorWithMethodRef () { Comparator<Integer> comparator = Integer::compare; System.out.println(comparator.compare(1 , 2 )); }
改进的 try-with-resourcs 在 Java 7 中可以实现资源的自动关闭,但是要求必须将需要自动关闭的所有资源必须在try子句中进行初始化
,否则编译不通过. 而在 Java 9 中可以将需要自动关闭的资源的实例放在 try 的小括号外哟,程序示例如下所示 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public void testTry () { InputStreamReader reader = null ; try { reader = new InputStreamReader(System.in); char [] buffer = new char [50 ]; int len; if ((len = reader.read(buffer)) != -1 ) { String s = new String(buffer, 0 , len); System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null ) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void testTryWithJDK7 () { try (InputStreamReader reader = new InputStreamReader(System.in)) { char [] buffer = new char [50 ]; int len; if ((len = reader.read(buffer)) != -1 ) { String s = new String(buffer, 0 , len); System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } } public void testTryWithJDK9 () { InputStreamReader reader = new InputStreamReader(System.in); OutputStreamWriter writer = new OutputStreamWriter(System.out); try (reader; writer) { char [] buffer = new char [50 ]; int len; if ((len = reader.read(buffer)) != -1 ) { String s = new String(buffer, 0 , len); System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } }
String存储结构的变更 从很多不同应用程序收集的信息表明,发现字符串是堆使用的主要组成部分. 而且,大多数字符串对象只包含一个字符,这样的字符只需要一个字节的存储空间,既而导致这些字符串对象的内部char数组中有一半的空间被闲置
JDK9 之前 String 底层使用 char 数组存储数据 private final char value[]
JDK9 将 String 底层存储数据改为 byte 数组存储数据 private final byte[] value
StringBuffer 和 StringBuilder 也同样做了变更,将以往 char 数组改为 byte 数组
快速创建只读集合 JDK9在 List、Set 和 Map 集合中新增 of 静态方法,快速创建只读集合,程序示例如下所示 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package pers.huangyuhui.jdk9;import org.junit.Test;import java.util.*;public class CollectionTest { @Test public void test () { List<String> list = new ArrayList<>(); list.add("A" ); list.add("B" ); list.add("C" ); list = Collections.unmodifiableList(list); System.out.println(list); Set<String> set = new HashSet<>(); set.add("E" ); set.add("F" ); set.add("G" ); set = Collections.unmodifiableSet(set); System.out.println(set); Map<String, String> map = new HashMap<>(); map.put("k1" , "v1" ); map.put("k2" , "v2" ); map.put("k3" , "v3" ); map = Collections.unmodifiableMap(map); System.out.println(map); } @Test public void testWithJDK9 () { List<String> list = List.of("A" , "B" , "C" ); System.out.println(list); Set<String> set = Set.of("E" , "F" , "G" ); System.out.println(set); Map<String, String> map = Map.of("k1" , "v1" , "k2" , "v2" , "k3" , "v3" ); System.out.println(map); } }
程序运行结果相同,如下所示 :
1 2 3 [A, B, C] [E, F, G] {k1=v1, k2=v2, k3=v3}
InputStream 终于有了一个非常有用的方法 : transferTo
, 可以用来将数据直接传输到 OutputStream,这是在处理原始数据流时非常常见的一种用法,示例代码如下所示 :
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void testTransferTo () throws FileNotFoundException { ClassLoader classLoader = this .getClass().getClassLoader(); InputStream is = classLoader.getResourceAsStream("from.txt" ); OutputStream os = new FileOutputStream("to.txt" ); try (is; os) { assert is != null ; is.transferTo(os); } catch (IOException e) { e.printStackTrace(); } }
增强的 Stream API Java 的 Stream API 是 Java 标准款最好的改进之一,让开发者能够快速运算,从而能够有效的利用数据并行计算. Java 8 提供的Stream能够利用多核架构实现声明式的数据处理. 而在 Java 9 中,Stream API 变得更好,Stream 接口中添加了4个新方法 ( takeWhile
, dropWhile
, ofNullable
, iterate的重载方法
), 及为你提供一个 Predicate( 判断条件 )来指定什么时候结束迭代. 除了对 Stream 本身的扩展, Optional 和 Stream 之间的结合也得到了改进,现在可以通过 Optional 的新对象 stream() 来将一个 Optional 对象转换为一个可能为空的 Stream 对象. 程序示例如下所示 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public void testStream () { List<Integer> list = Arrays.asList(45 , 43 , 76 , 87 , 42 , 77 , 90 , 73 , 67 , 88 ); list.stream().takeWhile((x) -> x < 80 ).forEach(System.out::println); List<Integer> list2 = Arrays.asList(45 , 43 , 76 , 87 , 42 , 77 , 90 , 73 , 67 , 88 ); list2.stream().dropWhile((x) -> x < 80 ).forEach(System.out::println); Stream<String> stringStream = Stream.of("AA" , "BB" , null ); System.out.println(stringStream.count()); List<String> list3 = new ArrayList<>(); list3.add("A" ); list3.add(null ); System.out.println(list3.stream().count()); Stream<Object> stream = Stream.ofNullable(null ); System.out.println(stream.count()); Stream<String> stream2 = Stream.ofNullable("Hello World" ); System.out.println(stream2.count()); Stream.iterate(1 , (x) -> x + 1 ).limit(10 ).forEach(System.out::print); Stream.iterate(1 , (x) -> x <= 10 , (x) -> x + 1 ).forEach(System.out::print); }
改进的 Optional 类 Optional 类是在JDK8中新增的类,主要是为了解决空指针异常. 在JDK9中对这个类进行了改进,主要是新增了三个方法 : stream
, ifPresentOrElse
和 or
stream
: 将 Optional转为一个 Stream,如果 Optional 没有值就返回一个 Stream.empty
ifPresentOrElse
: 如果 Optional 包含值,则对其包含的值调用函数 action,即 action.accept(value),这与 ifPresent 一致.与 ifPresent 方法的区别在于 ifPresentOrElse 还有第二个参数 emptyAction. 如果 Optional 不包含值,那么 ifPresentOrElse 便会调用 emptyAction,即 emptyAction.run()
or
: 如果 Optional 有值,返回 Optional 指定的值,否则返回一个预设的值
全新的 HTTP 客服端 API JDK9 中有新的方式来处理 HTTP 调用. 它提供了一个新的HTTP客户端(HttpClient),它将替代仅适用于 blocking 模式的HttpURLConnection( HttpURLConnection是在HTTP 1.0的时代创建的,并使用了协议无关的方法 ),并提供对 WebSocket 和 HTTP/2 的支持. 此外,HTTP 客户端还提供 API 来处理 HTTP/2 的特性,比如流和服务器推送等功能. 全新的 HTTP 客户端 API 可以从 jdk.incubator.httpclient 模块中获取. 因为在默认情况下,这个模块是不能根据 classpath 获取的,需要使用add modules
命令选项配置这个模块,将这个模块添加到 classpath中
javadoc 的 HTML5 支持 JDK8 生成的 java 帮助文档是在 HTML4 中,而HTML4 已经是很久的标准了. JDK9 的 javadoc 现支持HTML5 标准
更多 JDK9 的新特性描述请参阅 : What’s New in JDK9