北京时间2018年9月26日,Oracle 官方正式发布Java11,这是自Java8后支持的首个长期版本,Java11扩展支持到2026年,下面介绍Java11的一些新特性。
1. 局部变量类型推断
var str = "java";
等于
String str = "java";
局部变量类型推断就是左边的类型直接使用 var 定义,而不用写具体的类型,编译器能根据右边的表达式自动推断类型
注意:
1) var str; 这样不可以, 因为无法推断.
2) 局部变量中使用,所以,类的属性的数据类型不可以使用var.
3) var并不是真的关键字,仅是语法的改进,便于减少代码量的.
lambda表达式的形参也允许使用var,使用var的好处是在使用lambda表达式时给参数加上注解:
Predicate<String> p = (@Nullable var x) -> true; //正确
Predicate<String> p = (@Nullable x) -> true; //错误
2. 集合
List、Set 和 Map 都添加了of和copyOf方法,它们都用来创建不可变的集合,List.of 会根据给定的参数创建一个新的不可变的 list。List.copyOf 能创建 list 的不可变副本。
var list = List.of("git", "svn");
var copy = List.copyOf(list);
System.out.println(list == copy); //true
var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); //false
根据源码可以看出copyOf方法会先判断源集合是不是不可变集合,如果是,直接返回,否则调用of创建一个新的不可变集合。所以,第一个输出结果为true,list和copy指向同一个不可变集合,第二个输出结果为false,copy会生成一个新的实例。
注意:使用 of 和 copyOf 创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报java.lang.UnsupportedOperationException异常。
3.流
3.1 单个参数构造方法,参数可为null
Stream.ofNullable(null); // 正确,返回一个空的流
Stream.of(null); //报错
3.2 takeWhile方法:从流中一直获取判定器为真的元素, 一旦遇到元素为假, 就终止处理,留下前面为真的元素.
Stream<Integer> stream1 = Stream.of(3, 9, 20, 22, 40, 7);
Stream<Integer> stream2 = stream1.takeWhile(t -> t % 2 != 0);
stream2.forEach(System.out::println); //3,9
3.3 dropWhile方法:和上面的相反,去掉从流中一直判定器为真的元素, 一旦遇到元素为假, 就终止处理,留下为假及后面的元素.
Stream<Integer> stream1 = Stream.of(3, 9, 20, 22, 40, 7);
Stream<Integer> stream3 = stream1.dropWhile(t -> t % 2 != 0);
stream3.forEach(System.out::println); // 20, 22, 40, 7
3.4 iterate一个重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
// 有限的迭代
Stream<Integer> stream2 = Stream.iterate(1, t -> t < 1000, t -> (2 * t) + 1);
stream2.forEach(System.out::println);
4.Optional
//很方便的将Optional转换成流
Optional.of("java").stream().count(); // 1
//当一个空 Optional 时给它一个替代
Optional.ofNullable(null).or(() -> Optional.of("java")).get(); //java
Optional.of("java").orElseThrow(); // java
5.字符串
String str = " \t \r\n abc \t ";
str.isBlank(); // 判断字符串中的字符是否都是空白
str.strip(); // 去除字符串首尾的空白, 包括英文和其他所有语言中的空白字符
//以前的 trim()方法去除字符串首尾的空白字符, 只能去除码值小于等于32的空白字符
str.stripLeading(); // 去除字符串首部的空白
str.stripTrailing(); // 去除字符串尾部的空白
str.repeat(int n); // 将str复制n份,返回值是一个新字符串
// 如:"hello".repeat(3); //hellohellohello
str.lines().count(); // 行数统计
6.http客户端
新的 HttpClient 支持同步和异步方式。BodyHandlers 定义了期待的响应体类型(如字符串、字节数组或文件):
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
BodyHandler<String> responseBodyHandler = BodyHandlers.ofString();
HttpResponse<String> response = client.send(request, responseBodyHandler); //同步
String body = response.body();
System.out.println(body);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
BodyHandler<String> responseBodyHandler = BodyHandlers.ofString();
CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, responseBodyHandler); //异步
sendAsync.thenApply(t -> t.body()).thenAccept(System.out::println);
7.InputStream
transferTo: 一个非常有用的方法,可以用来将数据直接传输到 OutputStream.
@Test
public void test() throws Exception {
var cl = this.getClass().getClassLoader();
try (var is = cl.getResourceAsStream("file"); var os = new FileOutputStream("file2")) {
is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
}
}
其他:
1) 更简化的编译运行程序
以前:编译:javac hello.java 运行: java hello
现在:一步到位:java hello.java
注意:
a.执行源文件中的第一个类, 第一个类必须包含主方法
b.并且不可以使用别源文件中的自定义类, 本文件中的自定义类是可以使用的.
c.并没有生成class文件
2) jshell:
jshell这个交互性工具,让Java也可以像脚本语言一样来运行,可以从控制台启动 jshell ,在 jshell 中直接输入表达式并查看其执行结果。当需要测试一个方法的运行效果,或是快速的对表达式进行求值时,jshell 都非常实用。
3) Unicode 10
Unicode 10 增加了8518个字符, 总计达到了136690个字符. 并且增加了4个脚本.同时还有56个新的emoji表情符号.
4) Epsilon垃圾收集器
没有操作的垃圾回收器,一旦可用堆内存用完,JVM就会退出.
用法:-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
提供完全被动的GC实现, 具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量.
主要用途如下 :
性能测试(它可以帮助过滤掉GC引起的性能假象)
内存压力测试(例如,知道测试用例 应该分配不超过1GB的内存, 我们可以使用-Xmx1g –XX:+UseEpsilonGC, 如果程序有问题, 则程序会崩溃)
非常短的JOB任务(对象这种任务, 接受GC清理堆那都是浪费空间)
VM接口测试
Last-drop 延迟&吞吐改进
5) ZGC垃圾收集器:
ZGC, A Scalable Low-Latency Garbage Collector(Experimental):可伸缩,低延迟的垃圾收集器
ZGC, 这应该是JDK11最为瞩目的特性, 没有之一. 但是后面带了Experimental, 说明这还不建议用到生产环境.
特点:
GC暂停时间不会超过10ms
既能处理几百兆的小堆, 也能处理几个T的大堆(OMG)
和G1相比, 应用吞吐能力不会下降超过15%
为未来的GC功能和利用colord指针以及Load barriers优化奠定基础
初始只支持64位系统
6) FightRecorder:
飞机的黑盒子,记录仪。记录java虚拟机的运行细节,通过它可以知道GC如何工作,类如何加载,对象什么时候创建等等。