Java 11 的新特性(上)

JEP 181 Nest-Based Acess Control

這一提案是爲了加強自Java 1.1即引入的嵌套類設計。java

嵌套類主要有兩個用處。json

第一是由於其只使用於很短的代碼塊中,在Java8以前,這主要依靠實現一個匿名類來完成。Java8以後,這種用法能夠被lambda表達取代。app

另外一種用法是由於須要訪問另外一個類的內部。嵌套類具備和成員變量以及成員方法相同的訪問權限。異步

JEP181主要是爲了解決JVM級別的權限與源碼權限不一致的問題。async

代碼分析

public class JEP181 {

    public class Nest1 {
        private int var1;

        public void doSome() throws Exception {
            final Nest2 nest2 = new Nest2();
            nest2.var2 = 2;
            System.out.println(nest2.var2);
            final Field f2 = Nest2.class.getDeclaredField("var2");
            f2.setInt(nest2, 2);
            System.out.println(nest2.var2);
        }
    }

    public class Nest2 {
        private int var2;
    }

    public static void main(String[] args) throws Exception {
        JEP181 jep181 = new JEP181();
        JEP181.Nest1 nest1 = jep181.new Nest1();
        nest1.doSome();
    }
}

result:
java 11: 2 2
java 8: java.lang.IllegalAccessException

這一段代碼在Java8中是不正確的。會拋出java.lang.IllegalAccessException。主要問題出在f2.setInt(nest2,2),這裏因爲在Nest2中是private的,因此沒法直接set值。可是卻又能夠直接調用nest2.var2=2來設置該值,由於嵌套類是能夠訪問別的嵌套類的私有屬性的。Java 11修復了這個使人困惑的現象。ui

JEP 181 官方介紹

A field or method R is accessible to a class or interface D if and only if any of the following conditions are true:

...

R is private and is declared in a different class or interface C, and C and D, are nestmates

JEP 321 HttpClient

HttpClient在Java9開始引入,Java10對此有所更新。Java11根據一些反饋對API進行了一些改進,可是大部分都沒有變化。該API經過CompletableFutures提供了非阻塞request和response,
關於請求和響應的背壓機制以及流控制都由Java11新提供的Flow API來提供。debug

雖然API沒有什麼變化,可是實現幾乎所有重寫了。Java11的所有實現都是異步的(Java9,10的Http/1.1的實現是阻塞的).設計

同步

static void syncGet()
        throws IOException, InterruptedException, URISyntaxException {
        HttpClient httpClient = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://www.baidu.com"))
            .timeout(Duration.ofSeconds(20))
            .header("Content-Type", "application/json")
            .build();
        HttpResponse<Path> response =
            httpClient.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get("abc.txt")));
        log.debug("Response status code: " + response.statusCode());
        log.debug("Response headers: " + response.headers());
        log.debug("Response body: " + response.body());
    }

關於同步的用法都比較簡單,和別的不少http庫的設計也比較相像。code

異步

static void asyncGet() {
        HttpClient httpClient = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://www.baidu.com"))
            .build();

        CompletableFuture<String> strResponse =
            httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body);
        strResponse.whenComplete((resp, t) -> {
            if (t != null) {
                log.debug(t.getMessage());
            } else {
                log.debug(resp);
            }
        }).join();
    }

JEP 323 Local-Variable Syntax for Lambda Parameters

Java 9,Java 10引入了var用來簡化聲明變量的過程,Java 11進一步加強了該特性。get

list.sort((@NotNull var t1, @NotNull var t2) -> {
            if (t1.equals(t2)) {
                return 0;
            }
            return t1 > t2 ? 1 : -1;
        });

在Java 11以前,上述代碼未能正確執行。
(var x, var y)->...在通常狀況下並無什麼用,可是若是須要給lambda表達式變量添加註解的話,那麼lambda中可使用var就有了做用。

相關文章
相關標籤/搜索