JDK10

摘要:
1.局部变量类型的推断。1.在JDK10之前定义变量的问题是,许多人抱怨Java是一种强类型,需要引入大量模板代码。JDK10扩展了应用程序类数据共享,允许应用程序类加载器、内置平台类加载器和自定义类加载器加载存档类。
1 局部变量类型推断

1.1 JDK10之前定义变量存在的问题

  • 很多人抱怨Java是一种强类型,需要引入大量的样板代码。很明显类型声明往往被认为不是必要的。
  • JDK10之前的Java代码总中,声明一个变量是非常繁琐的:
package com.sunxiaping;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-01 10:08
 */
public class VariableDemo {

    /**
     * 每次定义变量都需要在变量名的左边声明类型,很麻烦。
     */
    @Test
    public void test() {
        String str = "abc";
        int i = 10;
        Boolean flag = false;
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
    }

}
  • 许多流行的编程语言都已经支持某种形式的局部变量类型推断,如JS中的var类型。

1.2 JDK10局部变量类型推断的使用

  • JDK10可以使用var进行局部变量类型推断:
package com.sunxiaping;

import org.junit.Test;

import java.util.ArrayList;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 11:21
 */
public class VariableDemo {

    @Test
    public void test(){
        var str = "abc";
        var i = 10;
        var flag = false;
        var list = new ArrayList<>();
        var stream = list.stream();
    }

}

1.3 局部变量类型推断的场景

  • 1️⃣局部变量。
package com.sunxiaping;

import org.junit.Test;

/**
 * 局部变量类型推断使用场景
 *
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 11:21
 */
public class VariableDemo {

    /**
     * 局部变量类型推断使用场景之:局部变量
     */
    @Test
    public void test2() {
        var x = "abc";
        System.out.println("x = " + x);
    }
}
  • 2️⃣循环内。
package com.sunxiaping;

import org.junit.Test;

/**
 * 局部变量类型推断使用场景
 *
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 11:21
 */
public class VariableDemo {

    /**
     * 局部变量类型推断使用场景之:循环内
     */
    @Test
    public void test2() {
        for (var x = 0; x < 100; x++) {
            var str = "abc";
            System.out.println("x = " + str + x);
        }
    }
}

1.4 局部变量类型推断不能使用的场景

  • 1️⃣成员变量。
  • 2️⃣方法参数。
  • 3️⃣方法返回值。

1.5 局部变量类型推断的注意事项

  • 1️⃣var不是关键字,只是一个保留字,意味着var可以作为类名、变量名使用,但是不建议。
  • 2️⃣var定义变量时必须立刻赋值,不然Java编译器怎么推断类型呢。
  • 3️⃣var不能同时定义多个变量。
2 将JDK的多个代码仓库合并到一个存储库中

2.1 该特性的动机

  • 多年以来,JDK的完整代码库已经被分解到许多的仓库中。在JDK9中,JDK的源码被分为8个仓库:root、corba、hotspot、jaxp、jaxws、jdk、langtools和nashorn。JDK的源码分成多个仓库这种情况在支持各种所需的源代码管理操作方面做得很差。特别是,不可能在相互依赖的变更集的存储库之间执行原子提交。比如:如果今天用于单个错误修复或者RFE的代码跨越了jdk和hotspot仓库,则无法在托管这两个不同仓库的目录中原子的对两个仓库进行更改。跨越多个存储库的更改是很常见的。

2.2 好处

  • 在JDK10中这些将被合并为一个,使得跨相互依赖的变更集的存储库运行atomic commit(原子提交)成为可能。
3 垃圾回收器接口

3.1 该特性的动机

  • 当前,垃圾回收器的代码分散,不方便新增新的垃圾回收器,也不利于移除现有垃圾回收器。
  • 通过引入一个干净的垃圾回收器接口来改善不同垃圾回收器的源代码的隔离。

3.2 该新特性的目标

  • JVM内部GC代码的更好模块化。
  • 使得在不影响代码库的情况下向JVM添加新的GC变得更加简单。
  • 使得从JVM构建中移除GC更容易。
4 G1引入并行Full GC

4.1 该特性的动机

  • G1是设计来作为一种低延时的垃圾回收器。G1收集器还可以进行非常准确的对停顿进行控制。从JDK7开始启用垃圾回收器,在JDK9中G1成为默认垃圾回收策略。截止到Java9,G1的Full GC采用的是单线程的算法,也就是说G1在发生Full GC时会严重影响性能。

4.2 该特性的效果

  • JDK10对G1进行了提升,G1引入并行Full GC算法,在发生Full GC时可以使用多个线程进行并行回收,能为用户提供更好的体验。
5 应用程序类数据共享

5.1 该特性的动机

  • JDK5中引入的类数据共享,将一组类预处理为共享的存档文件,然后可以在运行时对其进行内存映射以减少启动时间。当多个JVM共享同一个存档文件时,它还可以减少动态内存占用。
  • JDK5仅允许引导类加载器加载归档的类。JDK10对应用程序类数据共享进行了扩展,允许应用程序类加载器、内置平台类加载器和自定义类加载器加载已归档的类。

5.2 该特性的目标

  • 通过在不同的Java进程之间共享通用的类元数据以便减少占用空间。
  • 缩短程序启动时间。
6 线程本地握手

6.1 该特性的动机

  • Safepoint是Hotspot JVM中一种让应用程序所有线程停止的机制。为了要做一些非常之安全的事情,需要让所有线程都停下来它才好做。比如菜市场,人来人往,有人忽然要清点人数,这时候,最好就是大家都原地不动,这样好统计。Safepoint起到的就是这样一个作用。
  • JVM会设置一个全局的状态值。应用线程去观察这个值,一旦发现JVM把此值都设置为“大家都停下来”,此时每个应用程序就会得到这个通知,然后各自选择一个point(点)停了下来,这个point就叫Safepoint。待所有的应用线程都停了下来,JVM就开始做了一些安全级别非常高的事情了。
  • 比如:垃圾清理暂停,类的热更新,偏向锁的取消,各种debug的操作,然后,让所有线程都到就近的Safepoint停下来本来就需要较长的时间,而且让所有线程都停止下来显得非常粗暴。
  • 为此,JDK10引入了一种可以不同stop all threads的方式,就是Thread Local Handshake(线程本地握手)。

6.2 该特性的效果

  • 线程本地握手是在JVM内部相当低级别的更改,修改安全点机制,允许在不运行全局虚拟机安全点的情况下实现线程回调,使得部分回调操作只需要停掉单个线程,而不是停止所有线程。
7 基于Java的实验性JIT编译器

7.1 该特性的动机

  • Java编译器指的是JDK自带的javac指令。javac指令可以将Java源程序编译成.class字节码文件。字节码无法直接运行,但是可以在不同平台JVM中的解释器解释执行。由于一个java指令可能被翻译为十几或几十个对等的微处理器指令,这种模式执行的速度相当缓慢。

7.2 该特性的目的

  • 由于解释器效率低下,JVM中增加了JIT编译器,会在运行的时候有选择的将运行次数较多的方法编译为二进制代码,直接运行底层硬件上。花费少许的编译时间来节省稍后相当长的执行时间,JIT这种设计的确增加不少效率,但是它并没有达到最顶尖的效能,因为某些极少执行的java指令在JIT编译的时候额外花费的时间可能比解释器解释执行的时间还长,针对这些指令而言,整体花费的时间并没有减少。
  • Graal是基于Java的JIT编译器,这项JEP将Graal编译器研究项目引入到JDK中。为了让JVM性能和当前C++所写版本匹敌提供基础。
8 删除javah工具

8.1 什么是javah?

  • javah是用于生成C语言的头文件。

8.2 该特性的动机

  • 从JDK8开始,javah的功能已经集成到了javac中,并去掉了javah工具。
javac -h . 文件名.java
9 JDK10新增API

9.1 集合新增copyof方法

  • JDK10给java.util包下的List、Set和Map新增了一个静态方法copyof,copyof方法将元素放到一个不可修改的集合并返回。

  • 示例:

package com.sunxiaping;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 15:20
 */
public class ListDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        
        //copyof会将集合中的元素复制到一个新集合中,这个新集合是不可变的集合,不能进行增删改
        List<String> copyOfList = List.copyOf(list);

        System.out.println("copyOfList = " + copyOfList);

//        copyOfList.add("ee"); //java.lang.UnsupportedOperationException

    }
}

9.2 InputStream和Reader新增transferTo方法

  • JDK10给InputStream和Reader类中新增了transferTo方法,transferTo方法的作用是将输入流读数的数据使用输出流写出,常用于复制文件等操作。

  • 示例:

package com.sunxiaping;

import java.io.*;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 15:31
 */
public class InputStreamDemo {
    public static void main(String[] args) {

        try (InputStream inputStream = new FileInputStream("G:\test.txt");
             OutputStream outputStream = new FileOutputStream("G:\test1.txt")) {
            inputStream.transferTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

9.3 IO流添加Charset参数的方法

  • IO流中的很多类都添加了Charset参数,比如PrintStream、PrintWriter、Scanner等,通过Charset可以指定IO流操作文本时的编码。

  • 示例:

package com.sunxiaping;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 15:45
 */
public class PrintStreamDemo {
    public static void main(String[] args) throws IOException {
        PrintStream printStream = new PrintStream("G://test.txt", Charset.forName("UTF-8"));

        printStream.print("你好啊");

        printStream.close();
    }
}

9.4 ByteArrayOutputStream新增toString方法

  • JDK10给ByteArrayOutputStream新增了重载的toString(Charset charset)方法,通过指定的字符集编码,将缓冲区的内容给转换为字符串。

  • 示例:

package com.sunxiaping;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2020-12-02 16:09
 */
public class Demo {
    public static void main(String[] args) throws IOException {
        String str = "你好";
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);

        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];

        int len = 0;
        while ((len = bais.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }

        System.out.println(baos.toString(StandardCharsets.UTF_8));

        bais.close();
        baos.close();

    }
}

免责声明:文章转载自《JDK10》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JavaScript中的ArrayLinux下安装项目管理工具Redmine下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JSTL 标签库详细介绍资料

前言从jsp 1.1规范开始,jsp就支持在jsp中使用自定义标签了,自定义标签的广泛使用造成了程序员重复定义,这样就促成了jstl(javaserver pages standard tag library)的诞生。因为工作中需要用到jstl,但网上却苦于找不到有关jstl的中文资料,所以就有了这篇文章。jstl简介jstl是一个不断完善的开放源代码的j...

【ECMAScript5】ES5基础

一、语法 区分大小写。 变量是弱类型的,可以初始化为任意值,也可以随时改变变量所存数据的类型。 每行结尾的分号可有可无,但是建议加上。 注释 单行注释以双斜杠开头(//) 多行注释以单斜杠和星号开头(/*),以星号和单斜杠结尾(*/) 代码块:用{ } 包起来的 二、变量 使用 var (variable的缩写)运算符声明变量。 可以用一个var...

tomcat占用cpu比较多

在Linux中当Tomcat启动后,我们只是去查看应用是否能够正常访问来判断Tomcat启动是否正常。一般情况下这样看是没有问题的,但是有时候我们会发现当Tomcat使用了一段时间后,开始出现CPU或者内存飙升。此时,查看Tomcat日志也许无法看到有效信息,因此有必要了解一下Linux和jdk给我们提供的相关工具。 1、查看内存和CPU使用较高的进程信息...

Session优缺点

许多人利用Session变量来开发ASP(Active Server Pages)/JSP。这些变量与任何编程语言中通用的变量非常相似,并且具有和通用变量一样的优点和缺陷。任何命令都需要运行时间和存储空间(甚至GOTO’s语句如此),Session变量同样需要自己的运行时间和存储空间。过多地使用Session变量就会导致无法代码冗余,并且使服务器运行成本提...

Java在处理大数据的时候一些小技巧

 http://soft.chinabyte.com/database/258/12609258.shtml 众所周知,java在处理数据量比较大的时候,加载到内存必然会导致内存溢出,而在一些数据处理中我们不得不去处理海量数据,在做数据处理中,我们常见的手段是分解,压缩,并行,临时文件等方法;   例如,我们要将数据库(不论是什么数据库)的数据导出到一个文...

Arduino语法-变量和常量

变量的声明: int led=11 一般变量的声明方法为类型名+变量名+变量初始化值。变量名的写法约定为首字母小写 变量的作用范围又称为作用域,变量的作用范围与该变量在哪儿声明有关,大致分为如下两种: (1)全局变量:若在程序开头的声明区或是在没有大括号限制的声明区,所声明的变量作用域为整个程序。即整个程序都可以使用这个变量代表的值或范围,不局限于某个括...