提到Java 8则必须知道的新特性莫过于Lambda表达式和Stream API。经过三年多的时间后,Java 9于2017年9月21日正式Release。此次更新也是具有革命性的,共计超过150多项功能更新。归结起来,最重大的更新莫过于:模块化系统和jShell命令。
值得注意的是,从Java9开始,Java的计划发布周期为6个月,或者更短的时间。这是我之前总结的文章,由于公司内的网络不能上传所有文件,所以,一直没来得及生成博客。
截止到目前, 我去官网看了下Java已经出了Java 11。
https://www.oracle.com/technetwork/java/javase/downloads/index.html
在此需要重点说明的Java 9的新特性大概有18个。
旧版本面临的问题:
新功能的设计理念:模块独立,化繁为简。
新功能的目的:较少内存开销、简化类库、改进Java SE适应不同设备、改进安全性。
使用:
模块的 src 下创建 module-info.java 文件,在该文件中编写暴露的接口和需要引入模块。
产生背景:
Read Eval Print Loop:交互式解释器
在Java没有引入函数式编程之前,对Java语言冲击最大的莫过于Python和Scala(Spark内核就是用Scala语言编写的),而这两种语言(甚至更多的语言)都是支持REPL工具的。所以,Java不仅仅加入了其他语言的新特性,也加入了自己独有的REPL工具——jShell。
设计理念与目的: 即写即得、快速运行
默认已经导入的包:
按Tab键,自动补全:
罗列出当前窗口(会话)的有效代码:
查看此会话中声明的所有变量和方法:
还有更多的功能和操作,可以查看相关资料。
产生背景:
在老项目中要用一些新特性时,就需要考虑Java版本升级的问题,但是这样做太浪费时间、精力和资源,Java9就提供了对多版本的支持。
设计理念和目的:项目可以采用多个Java版本开发。
产生背景:java8引入(函数式编程思想)Lambda后,规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是一个抽象类。
在 Java 9 中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为 private 的了,此时方法将不会成为你对外暴露的 API的一部分。
interface MyInterface {
void normalInterfaceMethod();
default void methodDefault1() {
init();
}
public default void methodDefault2() {
init();
}
// This method is not part of the public API exposed by MyInterface
private void init() {
System.out.println(" 默认方法中的通用操作");
}
}
class MyInterfaceImpl implements MyInterface {
@Override
public void normalInterfaceMethod() {
System.out.println(" 实现接口的方法");
}
}
public class MyInterfaceTest {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.methodDefault1();
// impl.init();// 不能调用
}
}
产生背景:关于该特性,主要是对钻石操作符号进行了升级使用。
我们将能够与匿名实现类共同使用钻石操作符,如果是在Java8中,则如下代码会报错:
private List flattenStrings(List... lists) {
Set set = new HashSet<>(){};
for(List list : lists) {
set.addAll(list);
}
return new ArrayList<>(set);
}
编译报错信息: '<>' cannot be used with anonymous classes
但是,Java9进行了升级:
private List flattenStrings(List... lists) {
// anonymous classes can now use type inference
Set set = new HashSet<>(){};
for(List list : lists) {
set.addAll(list);
}
return new ArrayList<>(set);
}
产生背景:简化语法
设计理念和目的:对try语句进行简化。
Java8之前:
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();
}
}
}
Java8中已经有了一点改进,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在 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();
}
产生背景:规范代码
设计理念和目的:规范代码
在 java 8 中,标识符可以独立使用“ _ ” 来命名,但是,在 java 9 中规定“_”不再可以单独命名标识符了,如果使用则会报错。
产生背景:节省空间资源
设计理念和目的:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。
产生背景:要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。这样就有点麻烦。
设计理念和目的:简化操作和开发。
调用集合中静态方法 of(),可以将不同数量的参数传输到此工厂方法中。此功能可用于 Set 和 List,也可用于 Map 的类似形式。此时得到的集合,是不可变的:在创建后,继续添加元素到这些集合会导致“UnsupportedOperationException” 。
产生背景: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 对象。
产生背景:Mac 上,JDK 已经支持视网膜显示,但在 Linux 和 Windows 上,它并没有。此次更新便弥补了此缺憾。
设计理念、目的说明:使用比现在更多的现代 API:Direct2D for Windows和 GTK +,而不是 Xlib for Linux。图形,窗口和文本由此自动缩放。JEP 251 还提供处理多分辨率图像的能力,即包含不同分辨率的相同图像的文件。根据相应屏幕的 DPI 度量,然后以适当的分辨率使用图像。
个人感觉此项功能用的还是比较少的。
产生背景:
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中。
HttpClient client = HttpClient.newHttpClient();
HttpRequest req =HttpRequest.newBuilder(URI.create("http://www.atguigu.com")).GET().build();
HttpResponse response = client.send(req,HttpResponse.BodyHandler.asString());
System.out.println(response.statusCode());
System.out.println(response.version().name());
System.out.println(response.body());
产生背景:有许多API从java诞生起,就很少被人使用。
Java 9 废弃或者移除了几个不常用的功能。其中最主要的是Applet API,现在是标记为废弃的。随着对安全要求的提高,主流浏览器已经取消对 Java 浏览器插件的支持。HTML5 的出现也进一步加速了它的消亡。开发者现在可以使用像 Java Web Start 这样的技术来代替 Applet,它可以实现从浏览器启动应用程序或者安装应用程序。
同时,appletviewer 工具也被标记为废弃。
在之前我们一直使用的都是javac,此次java9推出了智能 java 编译工具( sjavac ),sjavac的第一个阶段始于 JEP139 这个项目,用于在多核处理器情况下提升 JDK 的编译速度。如今,这个项目已经进入第二阶段,即 JEP199,其目的是改进 Java 编译工具,并取代目前 JDK 编译工具 javac,继而成为 Java 环境默认的通用的智能编译工具。
JDK 9 还更新了 javac 编译器以便能够将 java 9 代码编译运行在低版本 Java 中。
产生背景:
日志是解决问题的唯一有效途径:曾经很难知道导致 JVM 性能问题和导致 JVM 崩溃的根本原因。不同的 JVM 日志的碎片化和日志选项(例如:JVM 组件对于日志使用的是不同的机制和规则),这使得 JVM 难以进行调试。
设计理念和目的:
解决该问题最佳方法:对所有的 JVM 组件引入一个单一的系统,这些 JVM 组件支持细粒度的和易配置的 JVM 日志。
产生背景:旧版本的java帮组文档是在HTML4中,现在符合HTML5标准
产生背景:
需要为java提供轻量级的JavaScript运行时环境,来整合JavaScript,并提高效率。
Nashorn 项目跟随 Netscape 的 Rhino 项目,目的是为了在 Java 中实现一个高性能但轻量级的 Javascript 运行时。Nashorn 项目使得 Java 应用能够嵌入 Javascript。它在 JDK 8 中为
Java 提供一个 Javascript 引擎。
JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的API。这个 API 使得 IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类,就能够分析 ECMAScript 代码。
产生背景:
Oracle 一直在努力提高 Java 启动和运行时性能,希望其能够在更广泛的场景达到或接近本地语言的性能。但是,直到今天,谈到Java,很多 C/C++ 开发者还是会不屑地评价为启动慢,吃内存。
简单说,这主要是因为 Java 编译产生的类文件是 Java 虚拟机可以理解的二进制代码,而不是真正的可执行的本地代码,需要 Java虚拟机进行解释和编译,这带来了额外的开销。
使用说明:
JIT(Just-in-time)编译器可以在运行时将热点编译成本地代码,速度很快。但是 Java 项目现在变得很大很复杂,因此 JIT 编译器需要花费较长时间才能热身完,而且有些 Java 方法还没法编译,性能方面也会下降。AoT 编译就是为了解决这些问题而生的。
在 JDK 9 中, AOT(JEP 295: Ahead-of-Time Compilation)作为实验特性被引入进来,开发者可以利用新的 jaotc 工具将重点代码转换成类似类库一样的文件。虽然仍处于试验阶段,但这个功能使得 Java应用在被虚拟机启动之前能够先将 Java 类编译为原生代码。此功能旨在改进小型和大型应用程序的启动时间,同时对峰值性能的影响很小。
目前的稳定版本就是Java 11。
后语:
这篇文章是很早之前写的,现在才放到博客上(公司的网络不允许上传各种文件所限),回望2018年互联网技术界,最火的莫过于人工智能、微服务(SpringCloud/SpringBoot/Dubbo/Zookeeper/Redis/Mycat等)、云平台。当前的计算模式和场景正在发生翻天覆地的变化,不仅对 Java 的发展速度提出了更高要求,也深刻影响着 Java 技术的发展方向。传统的大型企业或互联网应用,正在被云端、容器化应用、模块化的微服务甚至是函数(FaaS,Function-as-a-Service) 所替代。
虽然,Java是面向对象编程的,但随着技术的演进,又不断引进了其他语言的各种独有特性,比如面向函数/过程编程,可以说,每当引入一个新的特性时,都是对Java的本质思想的一次冲击。如果可以,我们作为一名程序员或者说是技术者,要时刻关注前沿科技和发展趋势才行,必须要多掌握热门语言才行!