2018年9月26日,Oracle 官方宣布 Java 11 正式发布,这是自 Java8 之后 Java 大版本周期变化后的第一个长期支持版本。这篇介绍的是 Java9 到 Java11 累积的一些新特性,只涉及语法和编码上的功能,其他的如工具和虚拟机改进不涉及。
本文源码地址:code-note
1. 接口 接口允许有私有方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 interface Enhance { default void defaultMethod () { init(); } private void init () { staticMethod(); } static void staticMethod () { System.out.println("static method in interface." ); } }
2. try 语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void tryTest () { String path = "/home/nathan/test.sh" ; try (var reader = new InputStreamReader (System.in)) { } catch (IOException e) { e.printStackTrace(); } var reader = new InputStreamReader (System.in); var writer = new OutputStreamWriter (System.out); try (reader; writer) { } catch (IOException e) { e.printStackTrace(); } }
3. I/O 流新特性 类 java.io.InputStream
中增加了新的方法来读取和复制 InputStream 中包含的数据。
readAllBytes:读取 InputStream 中的所有剩余字节。
readNBytes: 从 InputStream 中读取指定数量的字节到数组中。
transferTo:读取 InputStream 中的全部字节并写入到指定的 OutputStream 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void InputStreamTest () throws IOException { InputStream inputStream = EnhanceExample.class.getResourceAsStream("test.txt" ); byte [] arr = new byte [5 ]; inputStream.readNBytes(arr, 0 , 5 ); Assert.assertEquals("Java9" , new String (arr)); byte [] allBytes = inputStream.readAllBytes(); Assert.assertEquals("Java10Java11" , new String (allBytes)); InputStream inputStream1 = EnhanceExample.class.getResourceAsStream("test.txt" );; ByteArrayOutputStream outputStream = new ByteArrayOutputStream (); inputStream1.transferTo(outputStream); Assert.assertEquals("Java9Java10Java11" , outputStream.toString()); }
4. 集合、Stream 和 Optional 在集合框架中,Java 9 增加 了 List.of()、Set.of()、Map.of() 和 Map.ofEntries() 等工厂方法来创建不可变集合
1 2 3 4 5 6 @Test public void unmodifiableCollectionTest () { List<Integer> integers = List.of(1 , 2 , 3 ); Set<String> strings = Set.of("a" , "b" , "c" ); Map<String, Integer> stringIntegerMap = Map.of("a" , 1 , "b" , 2 , "c" , 3 ); }
Stream 中增加了新的方法 ofNullable、dropWhile、takeWhile 和 iterate;Collectors 中增加了新的方法 filtering 和 flatMapping。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Test public void streamTest () { List<Integer> list = Arrays.asList(1 , 2 , 4 , 5 , 3 , 2 , 8 ); list.stream().takeWhile(x -> x < 5 ).forEach(System.out::println); List<Integer> collect = Stream.of(1 , 2 , 3 , 4 , 5 ).dropWhile(i -> i%3 !=0 ).collect(Collectors.toList()); System.out.println(collect); Stream<Object> stream = Stream.ofNullable(null ); long count = Stream.of( Optional.of(1 ), Optional.empty(), Optional.of(2 )).flatMap(Optional::stream).count(); Assert.assertEquals(2 , count); Optional.empty().orElseThrow(); }
Stream 还提供一个 Predicate (判断条件)来指定什么时候结束迭代。
1 2 3 4 5 6 @Test public void iterateTest () { Stream.iterate(1 , i -> ++i).limit(5 ).forEach(System.out::println); Stream.iterate(1 , i -> i <= 5 , i -> ++i).forEach(System.out::println); }
5. 变量类型推断 从 Java10 开始变量不需要写具体类型,变量类型直接使用 var 定义,编译器能根据右边的表达式自动推断类型。
1 2 3 4 5 6 @Test public void var () { String str1 = "abc" ; var str2 = "abc" ; Assert.assertEquals(str1, str2); }
对象引用也可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void collection () { var list = new ArrayList <>(); list.add(123 ); list.add("abc" ); var v = new VariableTest (); System.out.println(v.getClass().getName()); Runnable runnable = () -> System.out.println("interface var" ); }
6. HTTP 客户端 Java 11 对 Java 9 中引入并在 Java 10 中进行了更新的 Http Client API 进行了标准化,Java 11 中的新 Http Client API,提供了对 HTTP/2 等业界前沿标准的支持,同时也向下兼容 HTTP/1.1,精简而又友好的 API 接口,与主流开源 API(如:Apache HttpClient、Jetty、OkHttp 等)类似甚至拥有更高的性能。
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.net.*;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.time.Duration;public class HttpClientExample { HttpClient client; @Before public void init () { client = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(20000L )).build(); } @Test public void reqTest () throws IOException, InterruptedException { var request = HttpRequest.newBuilder(URI.create("https://zguishen.com/" )).build(); String body = client.send(request, HttpResponse.BodyHandlers.ofString()).body(); System.out.println(body); } @Test public void getTest () { var request = HttpRequest.newBuilder() .uri(URI.create("https://api.github.com/users/zgshen" )) .header("Accept" , "application/vnd.github.v3+json" ) .timeout(Duration.ofSeconds(10000L )) .GET() .build(); client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .whenCompleteAsync((res, exp) -> { System.out.println(res.body()); }).join(); } @Test public void postTest () { var requestBody = "{'key':'val'}" ; var request = HttpRequest.newBuilder() .uri(URI.create("http://example.com/json" )) .header("Contend-Type" ,"application/json" ) .timeout(Duration.ofSeconds(10000L )) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .whenCompleteAsync((res, exp) -> { System.out.println(res.body()); }).join(); } @Test public void Http2Test () throws URISyntaxException { HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.NEVER) .version(HttpClient.Version.HTTP_2) .build() .sendAsync(HttpRequest.newBuilder() .uri(new URI ("https://zguishen.com/" )) .GET() .build(), HttpResponse.BodyHandlers.ofString()) .whenComplete((resp, t) -> { if (t != null ) { t.printStackTrace(); } else { System.out.println(resp.version()); System.out.println(resp.statusCode()); } }).join(); } }
7. 参考