JDK17都出了,学点JDK11新特性

JDK8 - 转- JDK11 -转- JDK17

JShell(JDK9开始支持)

G:\dowload\JDK\JDK11\jdk-11.0.2\bin ===> C:\Windows\System32\cmd.exe

image-20211028144848156

var 局部变量的类型推导

  • var 不可以作用修饰成员变量。注意var不是关键字,仅仅是语法的改进。

  • int var = 100;//是有效的

  • var不是关键字,注意var推断的是接收变量的类型,如果接收变量未定义,那么无效且编译不通过!

  • var a;//不成立,编译不通过,因为无法推断!

JDK1.7开始的:

List list = new ArrayList<>();//左边的泛型依赖右边的泛型

JDK9开始:

var temp = "Hello World" ;

等价于

String temp = "Hello World" ;

var的最主要的用途一般是用于lambda表达式中!
(@NotNull var t,@NotNull var y)->t.eques(y);

JDK11新添加API

集合API增强

创建固定长度的集合

@Test
    public void testList() {
        String[] tempNumber = {"abc", "def", "ghi", "jkl", "mno", "pqr"};
        //以前创建集合
        List<String> stringByList01 = new ArrayList<>();
        for (int i = 0; i < tempNumber.length; i++) {
            stringByList01.add(tempNumber[i]);
        }
        System.out.println(stringByList01);


        //第一次进阶
        stringByList01 = new ArrayList<>(Arrays.asList(tempNumber));
//注意Arrays.asList返回的也不是util包下的ArrayList,是Arrays内部类名称也为ArrayList,两个不等同,所以不能添加新元素,异常:不支持操作异常
        System.out.println(stringByList01);

        //JDK11 List.of(...)
        List<String> stringByList = List.of(tempNumber);
        System.out.println(stringByList);
 //stringByList.getClass() = > ImmutableCollections$ListN(不可改变的集合),返回的也不是util包下的ArrayList,也是不能添加新元素
    }

同理set创建固定集合

@Test
    public void tetSet(){
        Set<Integer> integers = Set.of(123, 23, 43, 53, 65, 76, 73, 34, 54);
        System.out.println(integers);
        //注意,如果set的of方法里面有重复元素,直接抛异常
        //IllegalArgumentException
        integers = Set.of(123, 23, 43, 53, 65, 123, 23, 43, 53);
        System.out.println(integers);
    }

JDK11对于流的改进

 @Test
    public void streamTest() {
        //Stream 流处理创建也是可以使用of方法
        Stream<String> stream = Stream.of("5", "2", "1", "4");
        //排序和打印
        stream.sorted(String::compareTo).forEach(System.out::println);
        //可以Stream.of(),但是不可以Stream.of(null);是空指针异常

        //JDK11的有传入null的流的创建
        Stream<Object> objectStream = Stream.ofNullable(null);
        System.out.println(objectStream);

        //JDK11的新方法takeWhile
        Stream<Integer> integerStream = Stream.of(2, 4, 6, 7, 8);
        //就是遍历判定是否满足条件,满足的放入新的流中,一旦遇到不满足的就即刻终止遍历
        Stream<Integer> takeWhile = integerStream.takeWhile(t -> t % 2 == 0);
        takeWhile.forEach(x -> System.out.print(x + ","));

        System.out.println();
        //JDK11的新方法dropWhile
        Stream<Integer> dropWhileStream = Stream.of(2, 4, 6, 7, 8);
        //就是遍历判定是否满足条件,不满足的丢弃,一旦遇到满足的就将它和他后面的元素丢入新的流中
        Stream<Integer> dropWhile = dropWhileStream.dropWhile(t -> t % 2 == 0);
        dropWhile.forEach(x -> System.out.print(x + ","));


        //JDK8 流的无限流,迭代
        Stream<Integer> iterate = Stream.iterate(1, t -> 2 * t + 1);
        iterate.limit(10).forEach(x -> System.out.print(x + ","));

        //JDK11 解决无限流,迭代:中间有一个条件终止无限流,转化为有限流
        Stream<Integer> youxianliu = Stream.iterate(1, t -> t < 1000, t -> 2 * t + 1);
        youxianliu.limit(10).forEach(x -> System.out.print(x + ","));

    }

String增强API

@Test
    public void stringTest() {
        //JDK11字符串新增方法
        String str = " \t \n";
        //判断字符串是否为空白:
        boolean blank = str.isBlank();
        System.out.println(blank);

        //JDK11.去除字符串首尾的空白:处理各种语言的空白字符
        String strip = str.strip();// 原来的首尾ASCII码小于32的空格去除:str.trim(),
        System.out.println(strip);


        //去除尾部或者首部的空白
        String index = str.stripLeading();
        String last = str.stripTrailing();
        
        // 判断字符串是否为空白
        " ".isBlank(); // true
        // 去除首尾空格
        " Javastack ".strip(); // "Javastack"
        // 去除尾部空格
        " Javastack ".stripTrailing(); // " Javastack"
        // 去除首部空格
        " Javastack ".stripLeading(); // "Javastack "
        // 复制字符串
        "Java".repeat(3);// "JavaJavaJava"
        // 行数统计
        "A\nB\nC".lines().count(); // 3

    }

Optional增强:Opthonal 也增加了几个非常酷的方法,现在可以很方便的将一个 Optional 转换成一个 Stream, 或者当一个空 Optional 时给它一个替代的。

	//java ~
    String res1 = Optional.of( "java ~" ).orElseThrow();
    System.out.println(res1);
 
    //1
    long res2 = Optional.of( "java ~" ).stream().count();
    System.out.println(res2);
 
    //java ~
    Object res3 = Optional.ofNullable( null )
            .or( () -> Optional.of( "java ~" ) )
            .get();
    System.out.println(res3);

输入流增强api:

transferTo,可以用来将数据直接传输到OutputStream,这是在处理原始数据流时非常常见的一种用法。

try {
        InputStream inputStream = TestInputStream.class.getClassLoader().getResourceAsStream("test.txt");
        var file = new File("/Users/xxx/test2.txt");
        try (var outputStream = new FileOutputStream(file)) {
            inputStream.transferTo(outputStream);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

HTTP客户端增强api

这是 Java 9 开始引入的一个处理 HTTP 请求的的孵化 HTTP Client API,该 API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你可以在 java.net 包中找到这个 API。

try {
        var request = HttpRequest.newBuilder()
                .uri( URI.create("http://t.weather.sojson.com/api/weather/city/101020100"))
                .GET()
                .build();
 
        var client = HttpClient.newHttpClient();
 
        // 同步
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
 
        //异步
        client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body)
                .thenAccept(System.out::println)
                .join();
    } catch (Exception e) {
        e.printStackTrace();
 
    }

工作中异常:IOException, InterruptedException, ExecutionException

读写文件

对Files类增加了writeStringreadString两个静态方法,可以直接把String写入文件,或者把整个文件读出为一个String:

Files.writeString(
    Path.of("./", "tmp.txt"), // 路径
    "hello, jdk11 files api", // 内容
    StandardCharsets.UTF_8); // 编码
String s = Files.readString(
    Paths.get("./tmp.txt"), // 路径
    StandardCharsets.UTF_8); // 编码

JDK11还带来了EpsilonGC,就是什么也不做的GC,以及ZGC,一个几乎可以做到毫秒级暂停的GC。ZGC还处于实验阶段,所以启动它需要命令行参数-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

ZGC

ZGC, 这应该是JDK11最为瞩目的特性, 没有之一. 但是后面带了Experimental, 说明这还不建议用到生产环境。 GC暂停时间不会超过10ms,既能处理几百兆的小堆, 也能处理几个T的大堆(OMG),和G1相比, 应用吞吐能力不会下降超过15%,为未来的GC功能和利用colord指针以及Load barriers优化奠定基础,初始只支持64位系统 ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。 GC是java主要优势之一,当GC停顿太长, 就会开始影响应用的响应时间.消除或者减少GC停顿时长, java将对更广泛的应用场景是一个更有吸引力的平台. 此外, 现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存, 并且无需长时间的GC暂停时间

用法 : -XX:+UnlockExperimentalVMOptions –XX:+UseZGC, 因为ZGC还处于实验阶段, 所以需要通过JVM参数来解锁这个特性

完全支持Linux容器(包括Docker)

许多运行在Java虚拟机中的应用程序(包括Apache Spark和Kafka等数据服务以及传统的企业应用程序)都可以在Docker容器中运行。但是在Docker容器中运行Java应用程序一直存在一个问题,那就是在容器中运行JVM程序在设置内存大小和CPU使用率后,会导致应用程序的性能下降。这是因为Java应用程序没有意识到它正在容器中运行。随着Java 10的发布,这个问题总算得以解决,JVM现在可以识别由容器控制组(cgroups)设置的约束。可以在容器中使用内存和CPU约束来直接管理Java应用程序,其中包括:

遵守容器中设置的内存限制

在容器中设置可用的CPU

在容器中设置CPU约束

Java 10的这个改进在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等环境均有效。

容器的内存限制

在Java 9之前,JVM无法识别容器使用标志设置的内存限制和CPU限制。而在Java 10中,内存限制会自动被识别并强制执行。Java将服务器类机定义为具有2个CPU和2GB内存,以及默认堆大小为物理内存的1/4。

支持G1上的并行完全垃圾收集对于 G1 GC,相比于JDK 8,升级到JDK 11即可免费享受到:并行的Full GC,快速的CardTable扫描,自适应的堆占用比例调整(IHOP),在并发标记阶段的类型卸载等等。这些都是针对G1的不断增强,其中串行Full GC等甚至是曾经被广泛诟病的短板,你会发现GC配置和调优在JDK11中越来越方便。

posted on 2021-10-28 19:21  白嫖老郭  阅读(794)  评论(0编辑  收藏  举报

导航