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