目录
JDK 11是自JDK 8以来的又一个LTS版本,是目前全球使用最多的LTS版本之一。下边看一下JDK 11的新特性
在Java 11中,针对String的操作进一步得到加强。避免在很常见的场景中引入额外的、复杂的API。
用来判断字符串是不是空字符"“或者trim()之后(” ")为空字符:
-
- String blankStr = " ";
- // true
- boolean trueVal = blankStr.isBlank();
将一个字符串按照行终止符(换行符\n或者回车符\r)进行分割,并将分割为Stream流:
- String newStr = "Hello Java 11 \n aaaaa \r 2021-09-28";
-
- Stream
lines = newStr.lines(); -
- lines.forEach(System.out::println);
输出结果为:
Hello Java 11
aaaaa
2021-09-28
按照给定的次数重复串联字符串的内容:
- String str = "JDK11";
- // 空字符
- String empty = str.repeat(0);
- // JDK11
- String repeatOne = str.repeat(1);
- // JDK11JDK11
- String repeatTwo = str.repeat(2);
-
去除字符串前后的“全角和半角”空白字符:
- String str = "JDK11\u3000";
- // str = 6
- System.out.println("str = " + str.length());
- // trim = 6
- System.out.println("trim = " + str.trim().length());
- // strip = 5
- System.out.println("strip = " + str.strip().length());
-
Java 11中可以更轻松地从文件中读取和写入字符串内容了,可以通过Files工具类提供的新的静态方法:
readString
writeString
分别进行读写文件的字符串内容
放在之前很麻烦了,特别是对IO流不熟悉的同学来说。现在简单几行就搞定了:
- String dir= "d://test/hello.txt";
- // 写入文件
- Path path = Files.writeString(Path.of(dir), "hello jdk 11");
- // 读取文件
- String fileContent = Files.readString(path);
- // hello jdk 11
- System.err.println(fileContent);
-
之前想集合转对应的数组很麻烦,要么用迭代;要么用Stream流,现在你可以这样:
- List
sampleList = Arrays.asList("张三", "java 11"); - // array = {"张三", "java 11"};
- String[] array = sampleList.toArray(String[]::new);
-
java.util.function.Predicate是我们很常用的断言谓词函数。在以前取反我们得借助于!符号,在Java 11中可以借助于其静态方法not来实现,这样语义就更加清晰了:
- List
sampleList = Arrays.asList("test", "JDK 11","jack"); - // [jack]
- List
result = sampleList.stream() - // 过滤以j开头的字符串
- .filter(s -> s.startsWith("j"))
- // 同时不包含11的字符串
- .filter(Predicate.not(s -> s.contains("11")))
- .collect(Collectors.toList());
-
局部变量类型推断就是左边的类型直接使用 var 定义,而不用写具体的类型,编译器能根据右边的表达式自动推断类型,
var 语法 : 局部变量的类型推断
注意 :
1 var a; 这样不可以, 因为无法推断
2 类的属性的数据类型不可以使用var.
Java 10之前,你需要这样声明一个String对象。
使用var的有点:在使用lambda表达式时给参数加上注解
(@Deprecated var x, @Nullable var y) -> x.process(y);
var可以用于修饰Lambda局部变量
在Java 10中引入的var来进行类型推断。在Java 10中它不能用于修饰Lambda表达式的入参,其实对于一个Lambda表达式来说它入参的类型其实是可以根据上下文推断出来的。
拿上面的例子来说,s -> s.startsWith(“j”)中的s肯定是字符串类型,因此在Java 11中var可以用于修饰Lambda局部变量
如果不声明var,就没有办法为输入参数添加@NotNull注解
- List
sampleList = Arrays.asList("张三", "java 11","jack"); - List
result = sampleList.stream() - // 过滤以j开头的字符串
- .filter((@NotNull var s) -> s.startsWith("j"))
- // 同时不包含11的字符串
- .filter(Predicate.not((@NotNull var s) -> s.contains("11")))
- .collect(Collectors.toList());
-
流是在 Java 8 中引入的,现在增加了三个新方法。
1,Stream.ofNullable
2,dropWhile
3, takeWhile
从单个元素构造流
- Stream.ofNullable(null)
- .count() // 0
-
方法都接受一个谓词来决定从流中放弃哪些元素
- Stream.of(1, 2, 3, 2, 1)
- .dropWhile(n -> n < 3)
- .collect(Collectors.toList()); // [3, 2, 1]
-
-
方法都接受一个谓词来决定从流中选用哪些元素
- Stream.of(1, 2, 3, 2, 1)
- .takeWhile(n -> n < 3)
- .collect(Collectors.toList()); // [1, 2]
Optionals 增加了非常方便的新方法,例如,现在可以简单地将 Optionals 转换为流,或者提供另一个 Optionals 作为空 Optionals 的回调
- Optional.of("foo").orElseThrow(); // foo
- Optional.of("foo").stream().count(); // 1
- Optional.ofNullable(null)
- .or(() -> Optional.of("fallback"))
- .get();
-
JDK 11上对这个特性的描述是:开发一个处理内存分配但不实现任何实际内存回收机制的GC,一旦可用堆内存用完,JVM就会退出。
它的主要用途有以下几个方面:
- 性能测试(它可以帮助过滤掉GC引起的性能假象)
- 内存压力测试
- 非常短的JOB任务
- VM接口测试
可以来尝试着使用一下它,首先编写一段程序:
public class EpsilonTest { public static void main(String[] args) throws Exception { var list = new ArrayList<>(); boolean flag = true; int count = 0; while (flag) { list.add(new Garbage()); if (count++ == 500) { list.clear(); } } } } class Garbage { private double d1 = 1; private double d2 = 2; /** * GC在清除本对象时会调用该方法 */ @Override protected void finalize() throws Throwable { System.out.println(this + " collecting"); } }
这是一个无限循环的程序,循环体不断创建Garbage对象并放入集合,当循环次数达到500时将集合清空,此时的500个对象均为垃圾,会被GC清理,清理时调用finalize()方法打印信息。运行这段程序,结果如下:
... com.itcast.Garbage@1e9c634c collecting java.lang.OutOfMemoryError: Java heap space at com.itcast.EpsilonTest.main(EpsilonTest.java:11) com.itcast.Garbage@1174213e collecting com.itcast.Garbage@2029a4b8 collecting ...当程序执行到某一刻时,内存溢出,程序终止。现在来使用一下Epsilon,启动参数: UnlockExperimentalVMOptions:解锁隐藏的虚拟机参数。
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xms100m -Xmx100m运行程序后,结果如下:
程序开始 Terminating due to java.lang.OutOfMemoryError: Java heap space会发现,控制台只输出了这么一句,说明被清除的集合中的对象并没有被回收,而且内存溢出的速度也非常快,
这说明该GC是并不会回收垃圾,它提供完全被动的GC实现,具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量
据说这是JDK11最为瞩目的特性,没有之一,是最重磅的升级。
ZGC的优势:
- GC暂停时间不会超过10毫秒
- 既能处理几百兆的小堆,也能处理几个T的大堆
- 和G1相比,应用吞吐能力不会下降超过15%
- 为未来的GC功能和利用colord指针以及Load barriers优化奠定了基础
ZGC是一个并发、基于region、压缩型的垃圾收集器,只有root扫描阶段会STW(strop the world,停止所有线程),因此ZGC的停顿时间不会随着堆的增长和存活对象的增长而变长。用法:-XX:UnlockExperimentalVMOptions -XX:+UseZGC