java 9 新特性

一、java 9 介绍:

java 9经历了几次跳票后,最终在2017年9月21日发布。

1.1java 9 中提供了哪些新特性?

java 9 提供了超过 150 项新功能特性,包括备受期待的模块化系统、可交互的 REPL 工具:jshell,JDK 编译工具,Java 公共 API 和私有代码,以及安全增强、扩展提升、性能管理改善等。可以说 Java 9 是一个庞大的系统工程,完全做了一个整体改变。具体来讲:
 模块化系统
 jShell 命令
 多版本兼容 jar 包
 接口的私有方法
 钻石操作符的使用升级
 语法改进:try 语句
 下划线使用限制
 String 存储结构变更
 便利的集合特性:of()
 增强的 Stream API
 多分辨率图像 API
 全新的 HTTP 客户端 API
 Deprecated 的相关 API
 智能 Java 编译工具
 统一的 JVM 日志系统
 javadoc 的 HTML 5 支持
 Javascript 引擎升级:Nashorn
 java 的动态编译器

官方提供的新特性列表:https://docs.oracle.com/javase/9/whatsnew/toc.htm%23JSNEW-GUID-C23AFD78-C777-460B-8ACE-58BE5EA681F6

1.2特性中英文对比

  

1.3JDK 9 的目录结构

  JDK_HOME包括子目录:bin  conf   include  jmods   legel  lib

没有jre的子目录

目录名内容
bin 目录包含所有命令。 在Windows平台上,它继续包含系统的运行时动态链接库。
conf 目录包含用户可编辑的配置文件,例如以前位于jre\lib目录中的.properties和.policy文件
include 目录包含要在以前编译本地代码时使用的C/C++头文件。 它只存在于JDK中
jmods 目录包含JMOD格式的平台模块。 创建自定义运行时映像时需要它。 它只存在于JDK中
legel 目录包含法律声明
lib 目录包含非Windows平台上的动态链接本地库。 其子目录和文件不应由开发人员直接编辑或使用

 二、模块化系统:Jigsaw ----->Modularity

2.1官方特性:

200:The Modular JDK

201:Modular Source Code

220:Modular Run-Time Images

260:Encapsulate Most Internal APIs

261:Module System

282:jlink: The Java Linker

2.2 产生背景及意义

谈到 Java 9 大家往往第一个想到的就是 Jigsaw 项目。众所周知,Java 已经发展超过 20 年(95 年最初发布),Java 和相关生态在不断丰富的同时也越来越暴露出一些问题:

 Java 运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~60MB的内存加载,主要原因是JVM需要加载rt.jar,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)

  1. 当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。不同版本的类库交叉依赖导致让人头疼的问题,这些都阻碍了 Java 开发和运行效率的提升。
  2. 很难真正地对代码进行封装, 而系统并没有对不同部分(也就是 JAR 文件)之间的依赖关系有个明确的概念。每一个公共
  3. 类都可以被类路径之下任何其它的公共类所访问到,这样就会导致无意中使用了并不想被公开访问的 API。
  4.  类路径本身也存在问题: 你怎么知晓所有需要的 JAR 都已经有了, 或者是不是会有重复的项呢?
  5.  同时,由于兼容性等各方面的掣肘,对 Java 进行大刀阔斧的革新越来越困难,Jigsaw 从 Java 7 阶段就开始筹备,Java 8 阶段进行了大量工作,终于在 Java 9 里落地,一种千呼万唤始出来的意味。
  6.  Jigsaw项目(后期更名为Modularity)的工作量和难度大大超出了初始规划。JSR 376 Java 平台模块化系统(JPMS, Java Platform Module System)作为 Jigsaw 项目的核心, 其主体部分被分解成 6 个 JEP(JDK Enhancement Proposals)。
  7.  作为java 9 平台最大的一个特性,随着 Java 平台模块化系统的落地,开发人员无需再为不断膨胀的 Java 平台苦恼,例如,您可以使用 jlink 工具,根据需要定制运行时环境。这对于拥有大量镜像的容器应用场景或复杂依赖关系的大型应用等,都具有非常重要的意义。

 本质上讲,模块(module)的概念,其实就是package外再裹一层,也就是说,用模块来管理各个package,通过声明某个package暴露,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。

2.3设计理念:

模块独立、化繁为简
模块化(以 Java 平台模块系统的形式)将 JDK 分成一组模块,可以在编译时,运行时或者构建时进行组合。
2.4 实现目标
 主要目的在于减少内存的开销
 只须必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
 改进 Java SE 平台,使其可以适应不同大小的计算设备
 改进其安全性,可维护性,提高性能

2.5 使用举例
注: IntelliJ IDEA 2017.3支持模块化特性,这里选择此开发环境。
        模块将由通常的类和新的模块声明文件(module-info.java)组成。该文件是位于java代码结构的顶层,该模块描述符明确地定义了我们的模块需要什么依赖关系,以及哪些模块被外部使用。在exports子句中未提及的所有包默认情况下将封装在模块中,不能在外部使用。

java 9demo 模块中的ModuleTest类使用如下:

package com.xiaomifeng1010.java;
import com.xiaomifeng1010.bean.Person;
import org.junit.Test;

import java.util.logging.Logger;

public calss ModuleTest{
    
    private static final Logger LOGGER=Logger.getLogger("java9test");

    public static void main(String[] args){
        Person p=new Person("马云",40);
        
            System.out.println(p);
        LOGGER.info("aaaa");
}
    @Test
    public void Test1(){
        System.out.println("hello");
    }
}

对应在java 9demo 模块的src 下创建module-info.java文件:

 

module java9demo{
    requires java9test;
    requires java.logging;
    requires junit;
}

requires:指明对其它模块的依赖。
在java9test 模块的指定包下提供类Person:

package com.xiaomifeng1010.bean;

public class Person {

    private String name;
    private int age;
    public Person() {

    }
    public Person(String name, int age) {

        this.name=name;
        this.age=age;
    }

    public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
   

要想在java9demo模块中调用java9test模块下包中的结构,需要在java9test的module-info.java中声明:

module java9test{

       export com.xiaomifeng1010.bean;
}

exports:控制着哪些包可以被其它模块访问到。所有不被导出的包默认都被封装在模块里面。

2.6 补充说明
关于更多Java 9 模块编程的内容请参考一本书:《Java 9 Modularity》 里面讲的比较详细,介绍了当前Java对jar之间以来的管理是多么的混乱,引入modularity之后的改变会是很明显的差别。

三、java的REPL(Read-eval-print-loop 交互式解析器)工具:Jshell命令

3.1 官方特性:

222:jshell: The Java Shell (Read-Eval-Print Loop)

3.2 产生背景
像Python 和 Scala 之类的语言早就有交互式编程环境 REPL (read - evaluate - print - loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。
3.3 设计理念
即写即得、快速运行
3.4 实现目标
      Java 9 中终于拥有了 REPL工具:jShell。利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行java的代码,而无需创建Java文件,无需跟人解释”public static void main(String[] args)”这句废话。
       jShell也可以从文件中加载语句或者将语句保存到文件中。
        jShell也可以是tab键进行自动补全和自动添加分号。

3.5 使用举例
调出jShell

因为我目前用的是JDK11,所以提示的版本也是11

 基本使用方法:

 Tips:在 JShell 环境下,语句末尾的“;” 是可选的。但推荐还是最好加上。提高代码可读性。

导入指定的包:

默认已经导入如下的所有包:(包含java.lang包)

只需按下 Tab 键,就能自动补全代码

列出当前 session 里所有有效的代码片段

查看当前 session 下所有创建过的变量

 查看当前 session 下所有创建过的方法

 Tips:我们还可以重新定义相同方法名和参数列表的方法,即为对现有方法的修改(或覆盖)。

使用外部代码编辑器来编写 Java 代码

会jshell 编辑器编辑代码,可以重写方法

 

 从外部文件加载源代码
指定目录下提供HelloWorld.java文件:

public void sayHello(){
    System.out.println("Happy New Year");
}

    sayHello();

使用/open命令调用:

open java文件路径

没有受检异常(编译时异常)

退出jShell

四:多版本兼容jar包

4.1官方特性

238:Multi-Release JAR Files

4.2 使用说明
          当一个新版本的Java出现的时候,你的库用户要花费数年时间才会切换到这个新的版本。这就意味着库得去向后兼容你想要支持的最老的Java版本(许多情况下就是Java 6 或者 Java7)。这实际上意味着未来的很长一段时间,你都不能在库中运用Java 9所提供的新特性。幸运的是,多版本兼容jar功能能让你创建仅在特定版本的Java环境中运行库程序选择使用的class版本。

举例1:

 说明:
在上述场景中, root.jar 可以在 Java 9 中使用, 不过 A或B 类使用的不是顶层的 root.A或root.B 这两个class, 而是处在“META-INF/versions/9”下面的这两个。这是特别为 Java 9 准备的 class 版本,可以运用 Java 9 所提供的特性和库。同时,在早期的 Java 诸版本中使用这个 JAR 也是能运行的,因为较老版本的 Java 只会看到顶层的A类或 B 类。

举例2:

 官方说明:
By this scheme, it is possible for versions of a class designed for a later Java platform release to override the version of that same class designed for an earlier Java platform release.

通过该方案,为以后的Java平台发布设计的相似版本,可以重写早期Java平台发布而设计的同一类的版本。

4.3 使用举例
步骤一:提供必要的类
在指定目录(E:\teach\01_Java9\multijar\src\main\java\com\xiaomifeng1010)下提供如下的类:

【Generator.java】

package com.xiaomifeng1010;

import java.util.HashSet;
import java.util.Set;

public class Generator {
	public Set<String> createStrings() { 
		Set<String> strings = new HashSet<String>(); 
		strings.add("Java"); 
		strings.add("8"); 
		return strings; 
		}
}

 【Application.java】

package com.xiaomifeng1010;
import com.xiaomifeng1010.Generator; 
import java.io.IOException; 
import java.util.List; 
import java.util.ArrayList;
import java.util.Set;

public class Application {
	public static void testMultiJar() {
		com.xiaomifeng1010.Generator gen = new Generator(); 
		System.out.println("Generated strings: " + gen.createStrings());
		} 
}

在如下目录(E:\teach\01_Java9\multijar\src\main\java-9\com\xiaomifeng1010)

下提供同名的类:
【Generator.java】

package com.xiaomifeng1010;


import java.util.Set;

public class Generator {
	public Set<String> createStrings() { 
		return Set.of("Java", "9");
		}
}

步骤二:打包
指令如下:
javac -d build --release 8 src/main/java/com/atguigu/*.java
javac -d build9 --release 9 src/main/java-9/com/atguigu/*.java
jar --create --main-class=Application --file multijar.jar -C build . --release 9 -C build9 .
步骤三:在java 9 及之前版本的环境下进行测试即可

五、语法改进:接口的私有方法

5.1官方特性

213:http://openjdk.java.net/jeps/213

Support for private methods in interfaces was briefly in consideration for inclusion in Java SE 8 as part of the effort to add support for Lambda Expressions, but was withdrawn to enable better focus on higher priority tasks for Java SE 8. It is now proposed that support for private interface methods be undertaken thereby enabling non abstract methods of an interface to share code between them.

翻译成中文的大概意思是:在java 8中,在接口中支持私有方法以此来作为对lambda表达式支持,但是java 8中没有实现这个功能,而现在java 9中建议对私有接口进行支持,从而使接口的非抽象方法可以共享代码。

5.2使用说明

Java 8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是一个抽象类。

在Java 9中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为private的了,此时方法将不会成为你对外暴露的API的一部分。

 5.3 使用举例:

public interface MyInterface {
	void normalInterfaceMethod();
	default void methodDefault1() { 
		init(); 
		}
	public default void methodDefault2() { 
		init(); 
		} 
	
	default void init() { 
		System.out.println("默认方法中的通用操作"); 
		} 
	
}
class MyInterfaceImpl implements MyInterface{ 
	@Override 
	public void normalInterfaceMethod() {
	System.out.println("实现接口的方法"); }

	@Override
	public void init() {
		// TODO Auto-generated method stub
		
	}

	
		
	}
 public class MyInterfaceTest{ 
	public static void main(String[] args) { 
		MyInterfaceImpl impl = new MyInterfaceImpl(); 
		impl.methodDefault1(); 
		// impl.init();//不能调用 
	
	}
}

六、语法改进:钻石操作符(Diamond Operator)使用升级

6.1 使用说明
我们将能够与匿名实现类共同使用钻石操作符(diamond operator)
在java 8中如下的操作是会报错的:

 6.2使用举例:

七、语法改进:try语句

 7.1 使用举例
在java 8 之前,我们习惯于这样处理资源的关闭:

InputStreamReader reader = null; 
    try{ 
        reader = new InputStreamReader(System.in); 
        //流的操作 
    reader.read(); 
}catch (IOException e){
 e.printStackTrace(); 
}finally{ 
if(reader != null){ 
try { reader.close(); 
} catch (IOException e) {
 e.printStackTrace();
 } 
} 
}

java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。如下例所示:

try(InputStreamReader reader = new InputStreamReader(System.in)){
 }catch (IOException e){
 e.printStackTrace(); 
}

java 9 中,用资源语句编写try将更容易,我们可以在try子句中使用已经初始化过的资源,此时的资源是final的:

InputStreamReader reader = new InputStreamReader(System.in);
 OutputStreamWriter writer = new OutputStreamWriter(System.out); 
try(reader;writer){ 
    //reader是final的,不可再被赋值 
    // reader = null; 
}catch (IOException e){ 
    e.printStackTrace(); 
}

八、语法改进:UnderScore(下划线)使用的限制

8.1 使用说明
在java 8 中,标识符可以独立使用“_”来命名:

 九、String存储结构变更

9.1 官方特性

JEP 254:Compact Strings

9.2 产生背景
Motivation
        The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.

译文:string类的当前实现将字符存储在char数组中,每个字符使用两个字节(16位)。从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且,大多数字符串对象只包含Latin-1字符。这样的字符只需要一个字节的存储空间,因此这样的字符串对象的内部字符数组中的一半空间将被闲置。

9.3使用说明

Description
        We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

译文:我们建议将字符串类的内部表示形式从UTF-16字符数组更改为字节数组加上编码标志字段。新的字符串类将根据字符串的内容存储编码为ISO-8859-1/Latin-1(每个字符一个字节)或UTF-16(每个字符两个字节)的字符。编码标志将指示使用哪种编码。

结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。

9.4 拓展:StringBuffer 与 StringBuilder

那StringBuffer 和 StringBuilder 是否仍无动于衷呢?
            String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM's intrinsic string operations.

官方文档译文:与字符串相关的类(如abstractStringBuilder、StringBuilder和StringBuffer)将更新为使用相同的表示,Hotspot VM的内部字符串操作也将更新。

十、集合工厂方法:快速创建只读集合

10.1官方特性

269:Convenience Factory Methods for Collections

10.2 产生背景
要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。

例如:

 缺点:我们一下写了五行。即:它不能表达为单个表达式。

当然,我们也可以稍微简单点处理:

10.3 使用说明

 Java 9因此引入了方便的方法,这使得类似的事情更容易表达。

 List firsnamesList = List.of(“Joe”,”Bob”,”Bill”);
调用集合中静态方法of(),可以将不同数量的参数传输到此工厂方法

中。此功能可用于Set和List,也可用于Map的类似形式。此时得到的集合,是不可变的:在创建后,继续添加元素到这些集合会导致 “UnsupportedOperationException” 。
由于Java 8中接口方法的实现,可以直接在List,Set和Map的接口内定义这些方法,便于调用。

10.4 使用举例

十 一、增强的 Stream API

11.1 使用说明

        Java 的 Steam API 是java标准库最好的改进之一,让开发者能够快速运算,从而能够有效的利用数据并行计算。Java 8 提供的 Steam 能够利用多核架构实现声明式的数据处理。
          在 Java 9 中,Stream API 变得更好,Stream 接口中添加了 4 个新的方法:dropWhile, takeWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。(见下例)

          除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。现在可以通过 Optional 的新方法 stream() 将一个 Optional 对象转换为一个(可能是空的) Stream 对象。(见下例)

11.2 使用举例
takeWhile()的使用:
用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的 Stream 中,takeWhile 返回从开头开始的尽量多的元素。

List<Integer> list = Arrays.asList(45,43,76,87,42,77,90,73,67,88); list.stream().takeWhile(x -> x < 50)
    .forEach(System.out::println); 
System.out.println();
 list = Arrays.asList(1,2,3,4,5,6,7,8);
 list.stream().takeWhile(x -> x < 5)
    .forEach(System.out::println);

dropWhile()的使用:
dropWhile 的行为与 takeWhile 相反,返回剩余的元素。

List<Integer> list = Arrays.asList(45,43,76,87,42,77,90,73,67,88); list.stream().dropWhile(x -> x < 50)
    .forEach(System.out::println);
 System.out.println(); 
list = Arrays.asList(1,2,3,4,5,6,7,8); 
list.stream().dropWhile(x -> x < 5)
    .forEach(System.out::println);

ofNullable()的使用:
Java 8 中 Stream 不能完全为null,否则会报空指针异常。而 Java 9 中的ofNullable 方法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空 Stream。

 Optional类中stream()的使用:

List<String> list = new ArrayList<>();
list.add("Tom"); 
list.add("Jerry"); 
list.add("Tim"); 
Optional<List<String>> optional = Optional.ofNullable(list);
 Stream<List<String>> stream = optional.stream(); 
stream.flatMap(x -> x.stream()).forEach(System.out::println);

十二、多分辨率图像 API

12.1 官方特性

251: Multi-Resolution Images
263: HiDPI Graphics on Windows and Linux

12.2 产生背景
在Mac上,JDK已经支持视网膜显示,但在Linux和Windows上,它并没有。在那里,Java程序在当前的高分辨率屏幕上可能看起来很小,不能使用它们。这是因为像素用于这些系统的大小计算(无论像素实际有多大)。毕竟,高分辨率显示器的有效部分是像素非常小。
JEP 263以这样的方式扩展了JDK,即Windows和Linux也考虑到像素的大小。为此,使用比现在更多的现代API:Direct2D for Windows和GTK +,而不是Xlib for Linux。图形,窗口和文本由此自动缩放。
JEP 251还提供处理多分辨率图像的能力,即包含不同分辨率的相同图像的文件。根据相应屏幕的DPI度量,然后以适当的分辨率使用图像。

12.3 使用说明
 新的API定义在java.awt.image包下
 将不同分辨率的图像封装到一张(多分辨率的)图像中,作为它的变体
 获取这个图像的所有变体
 获取特定分辨率的图像变体-表示一张已知分辨率单位为DPI的特定尺寸大小的逻辑图像,并且这张图像是最佳的变体。
 基于当前屏幕分辨率大小和运用的图像转换算法,
java.awt.Graphics类可以从接口MultiResolutionImage获取所需的变体。
 MultiResolutionImage的基础实现是
java.awt.image.BaseMultiResolutionImage

十三、全新的HTTP客户端API

13.1 官方特性

110:HTTP 2 Client

13.2 使用说明
HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年,HTTP2才成为标准。

 

HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。 HTTP/2允许服务器“push”数据:它可以发送比客户端请求更多的数据。 这使得它可以优先处理并发送对于首先加载网页至关重要的数据。
Java 9中有新的方式来处理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中。

13.3使用举例

举例:

HttpClient client = HttpClient.newHttpClient();
 HttpRequest req = HttpRequest.newBuilder(URI.create("http://www.atguigu.com")) 
.GET() .build(); 
HttpResponse<String> response = client.send(req, HttpResponse.BodyHandler.asString()); System.out.println(response.statusCode());
 System.out.println(response.version().name()); 
System.out.println(response.body());

十四、Deprecated的相关API

14.1 官方特性

211: Elide Deprecation Warnings on Import Statements
214: http://openjdk.java.net/jeps/214
277: Enhanced Deprecation
289: http://openjdk.java.net/jeps/289
291:Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector

14.2 使用说明
Java 9 废弃或者移除了几个不常用的功能。其中最主要的是 Applet API,现在是标记为废弃的。随着对安全要求的提高,主流浏览器已经取消对 Java 浏览器插件的支持。HTML5 的出现也进一步加速了它的消亡。开发者现在可以使用像 Java Web Start 这样的技术来代替 Applet,它可以实现从浏览器启动应用程序或者安装应用程序。
同时,appletviewer 工具也被标记为废弃。

十五、智能Java编译工具

15.1 官方特性

139:Enhance javac to Improve Build Speed.

199:Smart Java Compilation, Phase Two

15.2 使用说明
        智能java编译工具( sjavac )的第一个阶段始于JEP139这个项目,用于在多核处理器情况下提升JDK的编译速度。如今,这个项目已经进入第二阶段,即JEP199,其目的是改进Java编译工具,并取代目前JDK编译工具javac,继而成为Java环境默认的通用的智能编译工具。
       JDK 9 还更新了javac 编译器以便能够将 java 9 代码编译运行在低版本 Java 中。

十六、统一的JVM日志系统

16.1官方特性

158: Unified JVM Logging
271: Unified GC Logging

16.2 使用说明
日志是解决问题的唯一有效途径:曾经很难知道导致JVM性能问题和导致JVM崩溃的根本原因。不同的JVM日志的碎片化和日志选项(例如:JVM组件对于日志使用的是不同的机制和规则),这使得JVM难以进行调试。
解决该问题最佳方法:对所有的JVM组件引入一个单一的系统,这些JVM组件支持细粒度的和易配置的JVM日志。

十七、javadoc的HTML 5 支持

17.1 官方特性

224: HTML5 Javadoc
225: Javadoc Search

17.2 使用说明
jdk 8 :生成的java帮助文档是在HTML 4 中,而HTML 4 已经是很久的标准了。
jdk 9 :javadoc的输出,现在符合兼容HTML 5 标准。
下图是java8 中生成的html页面,如果想要找到一些类文档,必须在google中搜索。

下图是在java 9 中,添加了一个搜索框。

 十八、JavaScript引擎升级:Nashorn

18.1 官方特性

236:Parser API for Nashorn

192:Implement Selected ECMAScript 6 Features in Nashorn

18.2 使用说明
Nashorn 项目在 JDK 9 中得到改进,它为 Java 提供轻量级的 Javascript 运行时。Nashorn 项目跟随 Netscape 的 Rhino 项目,目的是为了在 Java 中实现一个高性能但轻量级的 Javascript 运行时。Nashorn 项目使得 Java 应用能够嵌入 Javascript。它在 JDK 8 中为 Java 提供一个 Javascript 引擎。
JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。这个 API 使得 IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类,就能够分析 ECMAScript 代码。

十九、java的动态编译器

19.1官方特性

243:Java-Level JVM Compiler Interface
295: Ahead-of-Time Compilation

19.2 产生背景
         Oracle 一直在努力提高 Java 启动和运行时性能,希望其能够在更广泛的场景达到或接近本地语言的性能。但是,直到今天,谈到 Java,很多 C/C++ 开发者还是会不屑地评价为启动慢,吃内存。
简单说,这主要是因为 Java 编译产生的类文件是 Java 虚拟机可以理解的二进制代码,而不是真正的可执行的本地代码,需要 Java 虚拟机进行解释和编译,这带来了额外的开销。
19.3 使用说明
       JIT(Just-in-time)编译器可以在运行时将热点编译成本地代码,速度很快。但是 Java 项目现在变得很大很复杂,因此 JIT 编译器需要花费较长时间才能热身完,而且有些 Java 方法还没法编译,性能方面也会下降。AoT 编译就是为了解决这些问题而生的。
       在 JDK 9 中, AOT(JEP 295: Ahead-of-Time Compilation)作为实验特性被引入进来,开发者可以利用新的 jaotc 工具将重点代码转换成类似类库一样的文件。虽然仍处于试验阶段,但这个功能使得 Java 应用在被虚拟机启动之前能够先将 Java 类编译为原生代码。此功能旨在改进小型和大型应用程序的启动时间,同时对峰值性能的影响很小。
       但是 Java 技术供应商 Excelsior 的营销总监 Dmitry Leskov 担心 AoT 编译技术不够成熟,希望 Oracle 能够等到 Java 10 时有个更稳定版本才发布。
       另外 JVMCI (JEP 243: Java-Level JVM Compiler Interface)等特性,对于整个编程语言的发展,可能都具有非常重要的意义,虽然未必引起了广泛关注。目前 Graal Core API 已经被集成进入 Java 9,虽然还只是初始一小步,但是完全用 Java 语言来实现的可靠的、高性能的动态编译器,似乎不再是遥不可及,这是 Java 虚拟机开发工程师的福音。
      与此同时,随着 Truffle 框架和 Substrate VM 的发展,已经让个别信心满满的工程师高呼“One VM to Rule Them All!”, 也许就在不远的将来 Ploygot 以一种另类的方式成为现实。

二十、小结

1.在java 9 中看不到什么?
1.1 一个标准化和轻量级的JSON API
一个标准化和轻量级的JSON API被许多java开发人员所青睐。但是由于资金问题无法在Java 9中见到,但并不会削减掉。Java平台首席架构师Mark Reinhold在JDK 9邮件列中说:“这个JEP将是平台上的一个有用的补充,但是在计划中,它并不像Oracle资助的其他功能那么重要,可能会重新考虑JDK 10或更高版本中实现。 ”
1.2 新的货币 API
对许多应用而言货币价值都是一个关键的特性,但JDK对此却几乎没有任何支持。严格来讲,现有的java.util.Currency类只是代表了当前ISO 4217货币的一个数据结构,但并没有关联的值或者自定义货币。JDK对货币的运算及转换也没有内建的支持,更别说有一个能够代表货币值的标准类型了。
此前,Oracle 公布的JSR 354定义了一套新的Java货币API:JavaMoney,计划会在Java 9中正式引入。但是目前没有出现在JDK 9 中。
不过,如果你用的是Maven的话,可以做如下的添加,即可使用相关的API处理货币:
 

<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>0.9</version>
</dependency>

代码参考,可以访问https://github.com/JavaMoney,里面已经给出了使用说明和示例。

 

 


      随着云计算和 AI 等技术浪潮,当前的计算模式和场景正在发生翻天覆地的变化,不仅对 Java 的发展速度提出了更高要求,也深刻影响着 Java 技术的发展方向。传统的大型企业或互联网应用,正在被云端、容器化应用、模块化的微服务甚至是函数(FaaS, Function-as-a-Service所替代。
 Java虽然标榜面向对象编程,却毫不顾忌的加入面向接口编程思想,又扯出匿名对象之概念,每增加一个新的东西,对Java的根本所在的面向对象思想的一次冲击。反观Python,抓住面向对象的本质,又能在函数编程思想方面游刃有余。Java对标C/C++,以抛掉内存管理为卖点,却又陷入了JVM优化的噩梦。选择比努力更重要,选择Java的人更需要对它有更清晰的认识。
 Java 需要在新的计算场景下,改进开发效率。这话说的有点笼统,我谈一些自己的体会,Java 代码虽然进行了一些类型推断等改进,更易用的集合 API 等,但仍然给开发者留下了过于刻板、形式主义的印象,这是一个长期的改进方向。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值