一、Java9中的新特性

1.1 JDK和JRE目录结构的改变

在这里插入图片描述在这里插入图片描述

1.2 模块化系统

模块之间包的调用

现有两个模块,结构如下
在这里插入图片描述

现在希望在第一个块的MoudleTest中使用第二个模块中的Person类,直接使用是不行的,使用需要引入暴露和导入的概念
如图:
首先在第二个模块中的src下。新建 moudle-info.java文件
并指明向外暴露的包
在这里插入图片描述

1
2
3
4
module java9test {
exports guigu.moudletest20210918;
}
123

然后再需要引用的模块的src下同样新建 moudle-info.java文件
指明需要引入的模块
在这里插入图片描述

1
2
3
4
module guigu20210918 {
requires java9test;
}
123

1.3 Java的REPL工具

1.3.1 jShell命令

产生背景

向Python 和Scala之类的语言早就有交互式编程环境(read - evaluate - print - loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前Java版本想执行代码,必须创建文件、声明类、提供测试方法方可实现

设计理念

即写即得

实现目标

  • Java 9中拥有的jShell。可以让Java可以像脚本语言一样运行,从控制台启动jShell,利用jShell可以在没有声明类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行java代码,而无需创建Java文件。
  • jShell也可以从文件中加载语句或将语句保存到文件中
  • jShell也可以是tab建进行自动补全和自动添加分号

在命令行直接输入 jshell就可以开始写语句了

在这里插入图片描述

在shell中编写Java代码也会有相应的提示在这里插入图片描述
/edit命令可以调出JShell Edit Pad,可以在窗口看见已经成功的输出
在这里插入图片描述也可以在JShell Edit Pad中进行修改,修改完成后点击Accept按钮提交修改后在shell内会有修改成功的提示
在这里插入图片描述
直接在shell命令内再次定义同名的变量或方法,后建的变量方法会覆盖之前的变量和方法

其他jshell命令
在这里插入图片描述

在这里插入图片描述

1.4 语法改进:接口的私有方法

Java 9 中,接口中可以定义访问权限为private的方法。
在这里插入图片描述
在这里插入图片描述

1.5 语法改进:钻石操作符使用升级

在Java8中与匿名实现类共同使用钻石操作符(diamond operator)是会报错的
编译报错信息:Cannot use '<>' with anonymous inner classes.

1
2
3
4
5
6
7
    Comparator<Object> com = new Comparator<>() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
123456

1.6 try结构的语法升级

Java8中try的资源关闭是自动的

java8自动关闭的前提要求,执行后必须关闭的资源的初始化必须在try子句中初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//java8之前的资源关闭都是在finally中完成
//Java8当中资源关闭操作是自动实现的
try(InputStreamReader reader = new InputStreamReader(System.in)) {

char[] cbuf = new char[20];
int len;
while ((len = reader.read(cbuf))!= -1){
String s = new String(cbuf, 0, len);
System.out.println(s);
}

} catch (IOException e) {
e.printStackTrace();
}

Java9中try

执行后必须关闭的资源的初始化可以在try子句中之外
此时的reader是声明为final的,在try内部不可修改

1
2
3
4
5
6
7
8
9
10
11
12
13
//java9
InputStreamReader reader = new InputStreamReader(System.in);
try (reader) {
char[] cbuf = new char[20];
int len;
while ((len = reader.read(cbuf)) != -1) {
String s = new String(cbuf, 0, len);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}

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

1
2
3
List<Integer> list1 = List.of(1,2,3,4,5);
list.add();//抛出异常UnsupportedOperationException

1.8 InputStream 加强

InputStream有了一个非常有用的方法,transferTo,可以用来将数据直接传输带OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例:

1
2
3
4
5
6
7
8
9
10
ClassLoader c1 = this.getClass().getClassLoader();


try (InputStream is = c1.getResourceAsStream("hello.txt");
FileOutputStream os = new FileOutputStream("src\\hello1.txt")) {
is.transferTo(os);
} catch (IOException e) {
e.printStackTrace();
}

1.9 增强的 StreamAPI

四个方法:

takeWhile()

从开头开始返回尽可能的多的满足条件的元素,一旦遇到不满足条件的就停止

1
2
3
4
5
List<Integer> list = Arrays.asList(12, 432, 654, 23, 765, 55, 28, 88);
list.stream().takeWhile(x -> x > 100).forEach(System.out::println);
System.out.println("*****");
list.stream().takeWhile(x -> x <700).forEach(System.out::println);

输出:

1
2
3
4
5
6
*****
12
432
654
23
12345

dropWhile()

与takeWhile相反,从开头开始遇到不满足条件的元素后,返回剩下的元素

1
2
3
List<Integer> list = Arrays.asList(23,43,45,55,56,54,32,2,45,89,7);
list.stream().dropWhile(x -> x < 50).forEach(System.out::print);

输出:

1
2
55 56 54 32 2 45 89 7

ofNullable()

形参变量是可以为null值的单个元素

1
2
3
Stream<Integer> stream = Stream.ofNullable(null);
System.out.println(stream.count());

输出

1
2
0
1

重载方法iterate

1
2
3
4
5
//        java8中创建无限流
Stream.iterate(0,x-> x+1).limit(10).forEach(System.out::println);

//java9中新增的重载方法
Stream.iterate(0,x -> x<100,x->x+1).forEach(System.out::println);

1.10 Optional获取Stream的方法

1
2
3
4
5
6
7
8
9
//Java9给Optional类提供新方法stream()
ArrayList<Object> list = new ArrayList<>();
list.add("Tom");
list.add("Jerry");
list.add("Tim");

Optional<ArrayList<Object>> optional = Optional.ofNullable(list);
Stream<ArrayList<Object>> stream = optional.stream();
stream.flatMap(x->x.stream()).forEach(System.out::println);

输出·

1
2
3
4
Tom
Jerry
Tim
123

二、Java10中的新特性

2.1 局部变量类型推断

要使用类型推断那么局部变量必须赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1、声明变量时,根据所赋的值,推断变量类型
var num = 10;

var list = new ArrayList<Integer>();
list.add(123);


//2、遍历操作
for(var i :list){
System.out.println(i);
System.out.println(i.getClass());
}

//3、普通遍历操作
for (var i = 0; i < 10; i++) {
System.out.println(i);
}

不能推断的情况

① 没有初始化的局部变量声明
②方法的返回类型
③方法的参数类型
④构造器的参数类型
⑤属性
⑥catch块

2.2 集合新增copyOf()

用于创建只读集合

1
2
3
4
5
6
7
8
var list1 =  List.of("java","Python","C");
var copy1 = List.copyOf(list1);
System.out.println((list1 == copy1));//true

var list2 = new ArrayList<String>();
var copy2 = List.copyOf(list2);
System.out.println((list2 == copy2));//false

上述两种输出不同的原因:

1
2
3
copyOf(Xxx coll): 如果参数coll本身是一个只读集合,则copyOf()返回值即为coll本身
如果参数coll()不是一个只读集合,copyOf()就会返回一个新的只读集合

三、Java11 中的新特性(LTS)

3.1 String中新增的方法

空白操作

方法 作用
isBlank 判断当前字符串是否空白
strip() 去除首尾空白
stripTrailing() 去除尾部空白
stripLeading() 去除首部空白

代码测试:

1
2
3
4
5
6
7
8
9
10
11
12
//boolean isBlank
System.out.println(" ".isBlank());

//strip() 去除首尾空白
System.out.println("-------"+" d\tdsad\t\t\t\tdsvdasv \t\t\t".strip()+"------");

//去除尾部空白
System.out.println("-------"+" d\tdsad\t\t\t\tdsvdasv \t\t\t".stripTrailing()+"------");

//去除首部空白
System.out.println("-------"+" d\tdsad\t\t\t\tdsvdasv \t\t\t".stripLeading()+"------");

输出·:

1
2
3
4
5
true
-------d dsad dsvdasv------
------- d dsad dsvdasv------
-------d dsad dsvdasv ------

复制操作 repeat(int count)

将当前字符串复制count次并返回复制后的字符

1
2
3
4
5
6
7
8
        //当字符串复制count次
System.out.println("abc".repeat(4));
true
-------d dsad dsvdasv------
------- d dsad dsvdasv------
-------d dsad dsvdasv ------
abcabcabcabc

行数统计

lines().count():统计当前字符串的行数

1
2
3
4
        System.out.println("abc\ndefg".lines().count());
1
2
1

3.2 Optional加强

加强后的Optional,可以很方便地将一个Optional转换成一个Stream,或者当一个空Optional时给它一个替代的

新增方法 描述 新增的版本
boolean isEmpty() 判断value是否为空 JDK11
isPresentOrElse(Consumer<? super T>action,Runnable emptyAction) value非空,执行参数1功能;如果是value为空,执行参数2功能 JOK9
Optional or (Supplier<? extends Optional<? extends T>>supplier) value非空,返回对应Optional:value为空,返回形参封装的Optional JDK9
Stream stream() value非空,返回仅包含此value的Stream;否则,返回一个空的Stream JDK9
T orElseThrow() value非空,返回value;否则抛异常:NoSuchElementException JDK10

部分方法代码举例
isPresent()isEmpty()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        Optional<Object> op = Optional.empty();

System.out.println(op.isPresent());//判断内部的value是否存在
System.out.println(op.isEmpty() );//判断内部的value是否为空

var opj = op.orElseThrow();

System.out.println(opj);//opj为空,抛出异常NoSuchElementException
false
true

java.util.NoSuchElementException: No value present
1234
isPresentOrElse(Consumer<? super T>action,Runnable emptyAction)`
`Optional<T> or (Supplier<? extends Optional<? extends T>>supplier)
//创建一个value为null的Optional
Optional<Object> op = Optional.empty();

var op1 = Optional.of("调用or时空值返回此Optional");
System.out.println(op.or(()->op1));
op.ifPresentOrElse(str -> System.out.println("value非空执行了参数一"),()-> System.out.println("value为空,参数二被执行") );
System.out.println("*****");

op = Optional.of("abc");

System.out.println(op.or(()->op1));
op.ifPresentOrElse(str -> System.out.println("value非空执行了参数一"),()-> System.out.println("value为空,参数二被执行") );
Optional[调用or时空值返回此Optional]
value为空,参数二被执行
*****
Optional[abc]
value非空执行了参数一

3.3 局部变量类型推断的升级

在var上添加注解的语法格式在jdk中是不能实现的。在JDK11中加入了这样的语法

1
2
3
4
5
6
7
//错误形式:必须要有类型,可以加上var
//Consumer<String> con = (@Deprecated t) -> System.out.println(t.toUpperCase());

//正确形式
//使用var的好处是在使用lambda表达式时给参数加上注解
Consumer<String> con1 = (@Deprecated var t)-> System.out.println(t.toUpperCase());

3.4 全新的Http客户端API

HttpClient

它将替代仅适用于blocking模式的HttpURLCollection,并提供对WebSocket 和 HTTP/2的支持
javaWeb详述

3.5 更简化的编译运行程序 java Javastack.java

Java11以前Java文件编译运行的步骤

1
2
3
4
5
//编译·
javac Javastack.java
//运行
java Javastack

在之前的学习中我们一直有要运行一个Java源代码必须先编译,再运行,两步执行操作,在java11里,通过一个java命令:java Javastack.java就可以直接解决

一个命令编译运行源代码的注意点

  • 执行源文件中的第一个类,所以第一个类必须包含主方法
  • 并且不可以使用其他源文件中的自定义的类,本文件中的自定义类是可以使用的。

3.6 ZGC

  • GC是Java主要优势之一。然而GC(垃圾回收机制)停顿太长,就会开始影响应用的响应时间。消除或减少GC停顿时长,Java将对更广泛的应用场景是一个更有吸引力的平台。
  • ZGC,A Scalable Low-Latency Garbage Collection(Experimental),ZGC大概是JDK11最为瞩目的特性。但是后面带来Experimental,说明这不建议用到生产环境
  • ZGC是一个是一个并发,基于region,压缩性的垃圾收集器,只有root扫描阶段会STW(stop the world),因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。