- 「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」。
- 当然 不论新老朋友 我相信您都可以 从中获益。如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力!
Java 11 为什么重要?
Java 11 是继 Java 8 之后的第二个 LTS(long-term support)版本。自 Java 11 起,Oracle JDK 将不再免费提供商业用途。
您可以在开发阶段使用它,但要在商业上使用它,则需要购买许可证。
Java 10 是最后一个可以下载的免费 Oracle JDK。
Oracle 从 2019 年 1 月开始就停止了对 Java 8 的支持。您需要支付更多的支持费用。
如果不这样做,虽然您可以继续使用它,但不会获得任何补丁/ 安全更新。
自 Java 11 起,Oracle 将不再为任何单个 Java 版本提供免费的长期支持(LTS)。
尽管 Oracle JDK 不再免费,但是您始终可以从 Oracle 或其他提供商(例如 AdoptOpenJDK,Azul,IBM,Red Hat 等…)下载 Open JDK 构建。
什么是 LTS Module
从 2017 年开始,Oracle 和 Java 社区宣布了向 Java 的新 6 个月节奏的转变。它已迁移到 Oracle Java SE 产品的长期支持(LTS)模型。
LTS 版本的产品将提供 Oracle 的首要和持续的支持,目标是每三年一次。
每个 Java 版本都以一两个主要特性为模型,这些特性驱动了版本的发布。任何障碍都会推迟发布和上市时间。Jigsaw 项目就是 Java 9 的一个主要特性,它多次推迟了发布日期,并且发布时间被推迟了超过 1.5
年。6 个月一版的发车节奏将让特性紧随。发布的列车每 6 个月有一个时间表。赶上这列火车的特征会被留下,否则他们就等下一班火车。
Oracle JDK 与 Open JDK
为了对开发人员更加友好,Oracle & Java 社区现在将 OpenJDK 二进制文件作为主要 JDK 进行推广。
这与早期的 JDK 二进制文件是由 Oracle 专有并由 Oracle 许可的模式相比,很大程度上减轻了人们的负担,因为 Oracle 对重新发布有各种限制。
然而,Oracle 将继续生产他们的 JDK,但仅限于长期支持版本。这是朝着对云和容器更友好的方向迈出的一步,因为开放 JDK 二进制文件可以作为容器的一部分分发。
Open JDK 的二进制文件每 6 个月发布一次,而 Oracle JDK 的二进制文件每 3 年发布一次(LTS版本)。
特性总览
在了解完了 Java 11 附带的负担之后,现在让我们作为开发人员分析 Java 11 中的重要功能。
以下是 Java 11 中的引入的部分新特性。关于 Java 11 新特性更详细的介绍可参考这里。
- 基于嵌套的访问控制(JEP 181)
- 使用单个命令运行Java文件(JEP 330)
- Lambda 参数的局部变量语法(JEP 323)
- 动态类文件常量(JEP 309)
- HTTP 客户端(JEP 321)
- Epsilon-无操作垃圾收集器(JEP 318)
- 可扩展的低延迟垃圾收集器-ZGC(JEP 333)
- Unicode 10(JEP 327)
- 低开销堆分析(JEP 331)
- API 变更
- 其他变更
- 删除 Java EE 和 CORBA 模块(JEP 320)
- 飞行记录器(JEP 328)
- ChaCha20 和 Poly1305 加密算法(JEP 329)
- 改进 Aarch64 内部特征(JEP 315)
- 弃用 Nashorn JavaScript 引擎(JEP 335)
- 传输层安全性(TLS)1.3(JEP 332)
- 弃用 Pack200 工具和 API(JEP 336)
一. 基于嵌套的访问控制(JEP 181)
在 Java 11 之前,从嵌套类访问主类的 private
方法是可能的:
public class Main {
public void myPublic() {
}
private void myPrivate() {
}
class Nested {
public void nestedPublic() {
myPrivate();
}
}
}
但是,如果我们使用反射,它就会给出一个 IllegalStateException
:
jshell> Main ob = new Main();
ob ==> Main@533ddba
jshell> import java.lang.reflect.Method;
jshell> Method method = ob.getClass().getDeclaredMethod("myPrivate");
method ==> private void Main.myPrivate()
jshell> method.invoke(ob);
| 异常错误 java.lang.IllegalAccessException:class REPL.$JShell$15 cannot access a member of class REPL.$JShell$11$Main with modifiers "private"
| at Reflection.newIllegalAccessException (Reflection.java:376)
| at AccessibleObject.checkAccess (AccessibleObject.java:647)
| at Method.invoke (Method.java:556)
| at (#5:1)
jshell>
这是因为 JVM 访问规则不允许嵌套类之间进行私有访问。我们能通过第一种方式访问是因为 JVM 在编译时为我们隐式地创建了私有的 桥接方法。
而且这发生在幕后。这种桥接方法会稍微增加已部署应用程序的大小,并可能使用户和工具感到困惑。
Java 11 引入嵌套访问控制解决了这一问题。
Java 11 将嵌套的概念和相关的访问规则引入了JVM。这简化了 Java 源代码编译器的工作。
为此,类文件格式现在包含两个新属性:
- 一个嵌套成员(通常是顶级类)被指定为嵌套主类。它包含一个属性(NestMembers)来标识其他静态已知的嵌套成员。
- 其他每个嵌套成员都有一个属性(NestHost)来标识其嵌套主类。
因此,要使类型 C 和 D 成为嵌套伙伴,它们必须具有相同的嵌套主类。如果类型 C 在其 NestHost 属性中列出 D,则它声称是 D 托管的嵌套的成员。如果 D 还在其 NestMembers 属性中列出 C ,则将验证成员资格。另外,类型 D 隐式为其所托管的嵌套成员。
现在,编译器无需生成桥接方法。
java.lang.Class
在反射 API 中介绍了三种方法:getNestHost()
,getNestMembers()
,和isNestmateOf()
,用于支持上述的工作。
更多请阅读:https://www.baeldung.com/java-nest-based-access-control
二. 使用单个命令运行Java文件(JEP 330)
该 JEP 是在学习 Java 早期阶段的一个友好功能,但是在实际的 Java 开发中没有太大的用处,我们都使用 IDE。
假设我们现在有以下的源代码(.java
文件):
public class HelloJava {
public static void main(String[] args) {
System