1.概述
Oracle在2018年9月发布了java 11,仅在其前身版本10后6个月。
java 11是继java 8 之后第一个长期支持的版本。Oracle在2019年一月份已经停止了对java 8 的支持。因此,大部分人会升级到java 11。
在本教程中,我们将看看选择java 11的原因。然后我们将会探索几个新特性,已移除的特性以及java11中引入的性能增强。
2.Oracle vs. Open JDK
Java10是最后一个免费的Oracle JDK版本,我们可以在没有许可证的情况下进行商业使用。从Java 11开始,Oracle不提供免费的长期支持。
值得感谢的是,Oracle继续提供Open JDK发布,我们可以下载免费使用。
除了Oracle,还有一些其他的Open JDK提供者可供我们选择。
Differences Between Oracle JDK and OpenJDK
3.开发者特性
让我们看看常见API的更改,以及其他一些对开发人员有用的特性。
3.1 新 String 方法
Java 11 String 类增加了一个新方法:isBlank, lines, strip, stripLeading, stripTrailing, and repeat.
String multilineString = "Baeldung helps \n \n developers \n explore Java.";
List<String> lines = multilineString.lines()
.filter(line -> !line.isBlank())
.map(String::strip)
.collect(Collectors.toList());
assertThat(lines).containsExactly("Baeldung helps", "developers", "explore Java.");
这些方法可以减少操作String对象涉及的样板代码数量,从不得不导入外部包中解脱出来。
在上面的例子中的strip方法,提供了与trim方法非常相似的功能,但有更好的控制以及Unicode支持。
3.2 新 File 方法
另外,Java11从文件中读取/写入文本更加容易。
我们可以使用File类新的的静态方法:readString 和 writeString
Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo", ".txt"), "Sample text");
String fileContent = Files.readString(filePath);
assertThat(fileContent).isEqualTo("Sample text");
3.3 集合到数组
java.util.Collection 接口有一个新的默认方法:toArray 。
default <T> T[] toArray(IntFunction<T[]> generator) {
return toArray(generator.apply(0));
}
这个方法可以更容易的从一个集合创建出一个正确类型的数组。
List sampleList = Arrays.asList("Java", "Kotlin");
String[] sampleArray = sampleList.toArray(String[]::new);
assertThat(sampleArray).containsExactly("Java", "Kotlin");
3.4 Not Predicate 方法
Predicate方法新增了一个静态not方法,很像negate方法,用来否定一个存在的Predicate。
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
示例:
List<String> sampleList = Arrays.asList("Java", "\n \n", "Kotlin", " ");
List withoutBlanks = sampleList.stream()
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toList());
assertThat(withoutBlanks).containsExactly("Java", "Kotlin");
not(isBlank)读起来比 isBlank.negate()更自然,该方法的一大优势就是也可以用于方法引用,像not(String::isBlank)。
3.5 Lambda本地变量语法
Java11在lambda参数中新增了本地变量语法(var 关键字)。
可以给本地变量添加修饰语,比如添加一个自定义注解。
List<String> sampleList = Arrays.asList("Java", "Kotlin");
String resultString = sampleList.stream()
.map((@Nonnull var x) -> x.toUpperCase())
.collect(Collectors.joining(", "));
assertThat(resultString).isEqualTo("JAVA, KOTLIN");
3.6 HTTP Client
java.net.http包的新HTTP client是在Java 9 引进的,在Java11成为了一个标准的特性 。
新的HTTP API 提升了整体性能并且支持HTTP/1.1和 HTTP/2。
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(20))
.build();
HttpRequest httpRequest = HttpRequest.newBuilder()
.GET()
.uri(URI.create("http://localhost:" + port))
.build();
HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
assertThat(httpResponse.body()).isEqualTo("Hello from the server!");
3.7 Nest Based Access Control
Java 11 引入了nestmates概念以及JVM内的相关访问规则。
Java 11 Nest Based Access Control
一组nest类包括 外部/main类以及和它嵌套的所有类。
assertThat(MainClass.class.isNestmateOf(MainClass.NestedClass.class)).isTrue();
嵌套类有NestMembers属性,外部类有NestHost属性。
assertThat(MainClass.NestedClass.class.getNestHost()).isEqualTo(MainClass.class);
JVM访问规则允许访问nestmates间的私有成员,然后在之前的Java版本,reflection API拒绝了访问。
Java11修复了这个问题,reflection API提供了查询新的类文件属性的工具。
Set<String> nestedMembers = Arrays.stream(MainClass.NestedClass.class.getNestMembers())
.map(Class::getName)
.collect(Collectors.toSet());
assertThat(nestedMembers).contains(MainClass.class.getName(), MainClass.NestedClass.class.getName());
3.8 运行Java文件
Java11的一个重大变化:再也不用Javac显示的(explicitly)编译Java源文件了。
之前:
$ javac HelloWorld.java
$ java HelloWorld
Hello Java 8!
现在,我们可以用Java命令直接运行文件:
$ java HelloWorld.java
Hello Java 11!
4.性能增强
4.1 Dynamic Class-File Constants
新的常量池格式:CONSTANT_Dynamic。
4.2 改进的Aarch64内部函数
4.3 无操作垃圾收集器
一个新的垃圾收集器Epsilon作为Java11的实验特性开始使用。
之所以称为No-op无操作是因为它分配内存但不收集任何垃圾。因此,Epsilon可用于模拟内存溢出错误。
显然,Epsilon不适应于典型的生产Java应用程序,但有一些具体的场景下是非常有用的:
- 性能测试
- 内存压力测试
- VM 接口测试
- 极其短时的任务Extremely short-lived jobs
可以使用 -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC flag启动。
4.4 Flight Recorder 飞行记录器
Java Flight Recorder(JFR)目前在Open JDK中开源,在Oracle JDK中用于商业产品。
JFR是一款分析用具,从运行的Java程序中收集诊断信息和分析数据。
启动一个120s的JFR记录,可以用下面的参数:
-XX:StartFlightRecording=duration=120s,settings=profile,filename=java-demo-app.jfr
JFR可用于生产环境,因为它的性能通常低于1%。我们可以获取保存在JFR文件中记录的数据。为了分析和可视化数据,我们需要用另一个工具JMC:JDK Mission Control
5.移除的和不推荐使用的模块
5.1 Java EE 和 CORBA
完全移除的:
- Java API for XML-Based Web Services (java.xml.ws)
- Java Architecture for XML Binding (java.xml.bind)
- JavaBeans Activation Framework (java.activation)
- Common Annotations (java.xml.ws.annotation)
- Common Object Request Broker Architecture (java.corba)
- JavaTransaction API (java.transaction)
5.2 JMC和JavaFX
JDK中不再包含JMC(JDK Mission Control),目前可以单独下载JMC的独立版本。
JavaFX模块同理。
5.3 不推荐使用的模块
- Nashorn JavaScript engine, including the JJS tool
- Pack200 compression scheme for JAR files
6.其他改变
- New ChaCha20 and ChaCha20-Poly1305 cipher implementations replace the insecure RC4 stream cipher
- Support for cryptographic key agreement with Curve25519 and Curve448 replace the existing ECDH scheme
- Upgraded Transport Layer Security (TLS) to version 1.3 brings security and performance improvements
- Introduced a low latency garbage collector, ZGC, as an experimental feature with low pause times
- Support for Unicode 10 brings more characters, symbols, and emojis
7.总结
在这个文章中,我们探索了Java11 的一些新特性。
我们简单了解了一下Oracle和Open JDK的区别,回顾了一些API的改变,以及一些其他的有用的特性,性能提升,已经移除和不再推荐使用的模块。