Java 已经很古老了吗?那些喋喋不休地谈论闪烁着灯光的前面板和软盘时代的老人们所使用的编程语言?或者它仍然很时尚,拥有所有最新的语言增强功能,可实现直观的编码和一流的性能?也许 Java 介于两者之间:一种成熟的语言,但内心年轻。
接近30年前的1995年5月23日,Java正式进入世界。它最初是一种名为“Oak”的机顶盒使能技术,Sun Microsystems 想象这种技术很快就会占领美国的客厅。无论如何,这个计划没有成功,一开始也没有成功。但该语言逐渐成为现代软件的核心基础之一,可以在从微型传感器芯片到大型服务器盒子的各种设备上运行。
从那时起,Java 的理念发生了巨大的变化。Sun 和 Oracle 在嫁接功能方面做得非常出色,既保持了语言的新鲜感,又不影响大部分核心功能。也许 Java 只是那些不断发展的语言之一。
我们确信的一件事是,“Java”这个大帐篷中的许多功能与最初设想的不同——通常是根本不同。程序员正在创建 1995 年、2005 年甚至 2015 年的人们无法识别的代码,但旧代码仍然可以运行。这是一个高质量的策展。Oracle 公司于 2010 年收购了 Sun,现在定期提供新版本并添加保持 Java 语言相关性的功能。
以下是 Java 的 11 种改变,大部分都是为了变得更好。
Java 编程比以前更好的 10 种方式(以及它不那么好的原因之一)
1. 虚拟线程(Virtual threads)
Java 的原始版本使开发人员有机会创建自己的Thread对象并控制代码在多线程和多核环境中的运行方式。虽然有总比没有好,但程序员很快就发现Thread对象相当大,并且需要花费太多时间来创建和销毁。在程序开始时创建永久线程池成为笨重线程的常见解决方法。
随着虚拟线程的到来,这一切在 Java 19 中发生了变化。现在,JVM 处理 Java 程序中分配系统资源的大部分工作。程序员指定并行性何时可用,以及运行时 JVM 在可以的情况下并发运行代码。虚拟线程对于像微服务这样的现代架构来说是一个福音,它更容易开发和支持。
2. 结构化并发编程(Structured concurrency)
轻量级线程只是一个开始。Java 正在添加一个并行性抽象模型,这将使??程序员和 JVM 更容易同时处理工作负载。新的结构化并发模型为程序员提供了将 Java 工作负载分解为任务的机会,然后将这些任务分组到范围中。范围被收集到在同一线程中一起工作的纤维中。
目标是为 Java 开发人员提供用于构建并行程序的标准样板模型,因此他们不需要每次都深入推理。结构化并发还使虚拟机更容易检测并发执行的机会并将其映射到处理器核心。
3. 不可变数据(Immutable data)
一开始,Strings 是一成不变的。一旦String创建,就永远无法更改。调用类似的函数toLowerCase会创建一个全新的String. 这使得 JVM 可以更简单地管理跨Threads 的安全性和同步。
现在,Java 程序员可以通过将其称为“记录”来为自己的对象指定相同的不可变规则。这简化了多线程安全、缓存和同步。代码列出了字段的名称和类型,JVM 处理其余的事情。equals、hashCode、 和 等常用方法toString是自动创建的。其余时间,JVM 确保Records 是不可变的,这简化了许多程序细节并加快了代码的运行速度。
4. 垃圾回收机制(Garbage Collection)
Java 始终处理内存分配和回收的许多细节,许多程序员乐于将这一功能委托给 JVM。但有时,最初的垃圾收集器会暂停足够长的时间,以至于用户会注意到性能何时滞后。
如今,程序员可以在四种垃圾收集器之间进行选择,它们使用各种不同的垃圾收集算法,并且专门针对不同类型的应用程序:
垃圾优先 (G1) 垃圾收集器是默认选择,可通过更短的暂停提供更好的吞吐量。G1 采用的技术源自 Java 垃圾收集早期迭代的经验教训,例如对最大的块进行洗牌以及对经常更改的小对象进行微调识别。
Z Garbage Collector 的设计具有非常低的延迟,这是 Web 服务器、流媒体服务和其他实时数据工作的要求。它还可以很好地处理非常大的堆,因为它被设计为可扩展到 16 TB RAM。
并发垃圾收集器将在后台运行,根本不停止应用程序。它最适合像交互式应用程序这样不应该暂停的工作,尽管它可能效率不高。
最后,并行收集器使用多个线程来更快地收集数据,但停止更难以预测。
开发人员不必拘泥于单一的垃圾收集方法,也不必求助于其他解决方案,例如通过重用对象来模拟自己的内存管理。现在有四种主要选择,每一种都提供了更多调整和实验的选项。
5. 模式匹配 (Pattern matching)
Java 团队还在一些最低语法级别上增强了该语言,为开发人员提供了更多选择来编写更清晰、更具表现力的逻辑。switch用于创建条件堆栈的关键字现在if-then-else提供模式匹配,这意味着指定各种情况的逻辑不限于诸如 之类的基本表达式equals。
使用这些模式编写的 Java 代码特别简洁,并且它不仅能够区分数据中的值,还能够区分对象类型。可以使用所有引用类型和空指针。当然,仍然支持具有失败语义的更传统的逻辑,因此旧代码可以继续平稳运行。
6. 简化的语法 (Streamlined syntax)
一开始,编写 Java 与编写 C 或 C++ 没有太大区别。大括号和分号在 Java 中的作用与在 C 中的作用大致相同。循环采用经典的三部分形式构建。尽管 Java 的内部结构与 Lisp 有着很深的联系,但 Java 的基本语法与 C 的语法并没有太大区别。
不过,最近添加的内容都借鉴了 Ruby 和 Python 等脚本语言的简单性。For 循环不需要拼写出每个细节,因为当您循环访问列表或数组时,编译器现在可以直观地了解它们。对于想要节省击键次数的程序员来说,匿名函数和 lambda 表达式也是不错的选择。
C 语言中的一些冗长和过多的标点符号仍然存在,但今天的 Java 程序员可以用更少的字符拼出复杂的结构。
7. 密封类(Sealed classes)
从一开始,JVM 的设计就是为了防止程序员可能错误地在程序中留下的许多常见安全漏洞。最新版本添加了更多选项。例如,密封类允许类创建者准确指定哪些类可以扩展它。这可以防止使用库的其他人扩展类并添加或覆盖某些原始功能。
密封类的运行速度也比传统类快一些,因为它们允许更积极的优化和内联。它们还可以简化方法调度。
8. 外部函数和内存(Foreign functions and memory)
Java 虚拟机被设计为一个有围墙的花园或类型安全的沙箱。虚拟机保护代码并防止代码本机运行时可能发生的许多常见攻击。
对于熟悉的程序员来说,最初的 Java 本机接口 (JNI) 有点像后门。Java 团队知道一些开发人员需要连接到用其他语言编写的库和堆栈,并且一些系统调用是必不可少的。因此他们在 JVM 的盔甲上打开了这个漏洞,并简单地警告了使用它的危险。
现在,我们有了外部函数和内存 API,目前是第三个预览版的 JEP。这个API将使与外部的连接变得更容易、更安全。现在,更多的工作可以用纯 Java 编写,这为普通 Java 程序员开始连接到通用系统内存提供了机会。该提案还增加了更好的防护措施,例如类型检查,以阻止一些最严重的潜在溢出攻击。
这个API将使Java代码更容易在系统编码中承担更多的低级任务和数据处理。对于 Java 程序员来说,这是一种摆脱沙箱的更安全的方式。
9. 向量 API(The Vector API)
许多资深 Java 程序员都知道,最初的Vector类更多的是一种数据结构,而不是一种数学工具。这是一个灵活且同步的存储对象的解决方案,与List.
新的Vector API 功能更多。它是一种数学数据处理工具,随着人工智能算法以与物理科学家和数学家或多或少相同的方式使用矩阵和向量,这种数学数据处理工具变得越来越普遍。各个元素可以是原始类型,并且支持许多基本数学运算(例如点积)。
了解Vector类和 API 之间差异的一个好方法是查看add方法的作用。在原始类中,它只是像所有其他 Collections 类一样将一个对象固定在数据结构的末尾。在 API 中,它用于以数学方式添加各个元素,更像工程师所期望的那样。
Vector API 还承诺开放一些较新的 SIMD 处理器的强大计算能力,使 Java 程序员能够编写可以处理许多长向量的代码。
10. 更好的空值处理(Improved null processing)
该对象是空指针吗?许多 Java 代码专门用于检查、双重检查、然后三次检查对象。为了简化代码并加快速度,Java 慢慢地添加了以更优雅的方式处理空指针的功能。例如, Stream API可以处理长数据流,并且如果偶尔出现空值也不会挂起。类Optional包装器可能包含也可能不包含实际对象,从而使代码能够良好地流动。如果您仍然想检查 null 性,可以使用 null 安全运算符 ( ?.) 来以非常简洁的方式测试 null 。
Java 一直都是相当免费的,至少对于程序员来说是这样。从一开始,Sun 就希望通过免费的工具和硬件来吸引开发人员,并于 1997 年采取了大胆的举措,开源了该语言及其虚拟机的许多部分。直到最近,开发人员或多或少可以编写一次并在任何地方运行,而无需支付一毛钱。
现在,情况变得更加模糊。Oracle 的许多 Java 版本都是免费的,但有些版本需要带有奇怪条款的许可证。甲骨文似乎希望程序员能够享受不受金钱限制的创作自由,但同时也希望从那些从 Java 中产生大量长期收入的企业中提取税收或租金。实际上,这意味着对 Oracle 所谓的 Java订阅功能进行收费。所以,Java仍然是免费的,除非你想升级它用于商业用途。