paint-brush
为什么 Java 仍然流行经过@shai.almog
2,671 讀數
2,671 讀數

为什么 Java 仍然流行

经过 Shai Almog6m2022/09/27
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

现在是发布这篇文章的好时机,正好在 Java 19 发布之际。第一篇文章大多是无稽之谈和过时的点击诱饵。第二篇文章抱怨更多与 Jakarta EE 和 JVM 中的程序员美学有关。我们需要 getter/setter 的唯一一点是在非常特定的设置(例如 JPA)中,Lombok 再次完美地解决了这个问题。运算符**不能**重载的事实是一个巨大的好处。 Java 是关于“缓慢而稳定”的,也是 Java 长寿的主要原因。

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - 为什么 Java 仍然流行
Shai Almog HackerNoon profile picture

这是发布此内容的好时机,正好在 Java 19 发布时。是的,另一个“我的语言更好”的帖子。不,我不想写。但有时人们的糟糕预测会战胜我。在这种情况下,该帖子以评论开始,我最终决定将其变成帖子。这篇主要抱怨 Quarkus的帖子加强了这一点(如果我可以补充的话,有点不公平)。


第一篇文章大多是废话和过时的点击诱饵。我将在以下声明中向您总结:


  • 获取器/设置器
  • 缺少专门针对集合上的[]和任何东西上的+的运算符重载
  • 已检查的异常
  • 依赖管理


第二篇文章的抱怨与 Jakarta EE 和 JVM 中的一般程序员美学更相关。特别是使用注释进行验证和类似声明。这是一篇消息灵通得多的文章,但有几个缺陷,我将在接近尾声时加以说明。

Getter 和 Setter

现代 Java 不需要 Getter 和 setter。我们从 Java 14 开始就有记录,尽管有些说法相反,Lombok 仍然很好。我们需要 getter/setter 的唯一一点是在非常特定的设置(例如 JPA)中,Lombok 再次完美地解决了这个问题。


这篇文章对 Java 中缺乏语法糖特性进行了长篇大论。这是故意的。如果您对最新的语法细微差别感兴趣,可以查看 Kotlin。 Java 是关于“缓慢而稳定”的。这是一件好事,也是 Java 长寿的主要原因。

语法糖和运算符重载

现代 Java 包括 switch、var、多行字符串等模式。一些即将推出的功能包括字符串模板。字符串模板支持需要一段时间,因为 Java 想要“做对”。 API 级别对此有一些支持(并且已经有一段时间了)。这不是高性能的。字符串模板的目标是创建一个激进的可覆盖语法,它允许以下内容:


 ResultSet rs = DB."SELECT * FROM Person p WHERE p.last_name = \{name}";


更新:由于这篇文章的发布,开发人员错误地认为上面的代码是一个 SQL 注入漏洞。它不是。这看起来像字符串替换,但它是使用该语法生成参数化 SQL 调用的代码。


请注意, name是编译器将动态检查并从作用域获取的变量!

DB可以由开发人员自定义实现,不需要“内置”,因此您可以就地构建复杂的模板。


但是让我们谈谈我们今天拥有的 Java,而不是 6 个月后的 Java。十年或更长时间以来,使用 append 一直不是String的推荐。使用最高效且更易于阅读的+ 。关于集合, get()[]之间的区别实际上是四个字符。这些角色很重要。我们可以轻松地覆盖它。我们也可以理解语义上的差异。 Java 数组非常快,在许多情况下本机速度很快。收藏不能这么快,我们可以立即在这里看到这一点的事实非常有价值。


运算符不能重载的事实是一个巨大的好处。如果我看到a + b我知道这是一个字符串或一个数字而不是一些隐藏的方法。这是 Java 的最大优势之一,也是它流行了近 30 年而其他语言被抛在一边的原因之一。 Java 的语法是为大规模阅读而设计的。当你的项目有 100 万行甚至 100k 行代码时,问题就会转移。此时,在调试问题时发现模块 Y 中的程序员 X 错误地覆盖了运算符是很困难的。那时语法应该很简单,您最初节省的任何小成本都将以 10 倍的利息支付。随着代码变得更加复杂和老化,简单翻转的定义。再加上工具的强大功能,可以大规模解析严格的简单代码,这将带来更大的好处。

检查异常

检查的异常是可选的。但它们是 Java 中最好的特性之一。如此多的代码意外失败。当您将构建东西作为一种爱好时,它可能没问题。当你想构建一个专业的应用程序时,你需要处理每一个错误。检查的异常可以帮助您避免这种废话。由于懒惰,人们讨厌检查异常。 Java 保护您免受自己的侵害。

不应该有我建立网络连接、数据库连接、打开文件等并且不需要处理潜在错误的情况。我可以踢它,但随后检查的异常迫使我继续在某个地方踢它。这是一个了不起的功能。

依赖项

我对 Maven 和 Gradle 有很多问题。但是当你将它与几乎任何其他依赖系统进行比较时,它们做得很好。他们有问题,但您无法将它们与比较年轻的货物(例如几乎没有包裹的货物)进行比较。 Maven 中心非常庞大,拥有 27 TB 的 jars 和 4960 亿个请求。它完美地滴答作响,几乎没有停机时间。


NPM 等其他工具完美地展示了 maven 的优势。如果在 maven 中的依赖是一个问题,那么 NPM 有 100 倍的问题并且没有监督。随着这些事情的发展,出现了复杂性。尤其是市场上有多个版本的 Maven。然而,maven 和 gradle 为他们做的事情之一就是工具。在许多情况下,IDE 可以帮助解决问题并立即找到修复程序。

Java中的文化问题

第二篇文章更有趣,在某种程度上我同意。 Java 开发人员倾向于将每个问题都变成更复杂的问题。在某些情况下,这是必要的,Java 是编程平台中重达 800 磅的大猩猩,其解决方案经常被过度设计。这往往比动力不足要好,但它确实有代价。

为什么要使用注释进行验证

这篇文章确实提出了一个有趣的例子,对于不经意的观察者来说,这似乎是“正确的事情”,但却是有问题的。

 @NotNull @Email String noReplyEmailAddress

作者声称这很糟糕,应该实现自定义类型,例如:

 public record EmailAddress(String value) { public EmailAddress { // We could've used an Either data type, ofc; Objects.requireNonNull(value); // regexp could be better if (!value.matches("^[^@\\s]+@\\S+$")) throw new IllegalArgumentException( String.format("'%s' is not a valid email address", value)); } }

这在 Java 中是完全可能的,因为上面的代码是有效的 Java 代码。但它有几个问题,这就是我们进行 bean 验证的原因。


  • 这无法优化 - Bean 验证可以通过框架向上移动到验证链。它甚至可以在客户端代码中无缝验证,因为它是一个声明式 API。这里我们需要实际执行构造函数来执行验证。
  • 声明性注释可以向下移动以无缝应用数据库约束等。
  • 我们可以一次应用多个注释
  • 语法更简洁


结果,注释可能会让人感觉很奇怪并且不强制输入。确实如此。但它们提高了性能和功率。它们的使用背后有很多想法和常识。我明白作者的意思,我也不是 IoC 的忠实粉丝,但在这种特定情况下,他是不正确的。

最后

这篇文章在防守上花了太多时间。是时候换档了。 Java 已经存在了将近 30 年,并且仍然大部分与 Java 1.0 兼容。那太棒了,无与伦比!

其保守方法的强大之处之一是它可以在没有任何人注意到发生了什么的情况下进行惊人的“幕后”优化。 Java 9 完全取代了字符串在内存中的无缝表示方式,并显着减少了 RAM 的使用。同样,Loom 将提高 Java 同步应用程序的吞吐量。 Valhalla 将进一步提高收集性能并统一 Object/Primitive 的划分。 Panama 将最终摆脱 JNI 并使与本地代码集成的过程更加愉快。


好消息是 JVM 是一个大帐篷。如果您不是 Java 的粉丝,Kotlin 或 Scala 可能适合您的口味。 JVM 的好处是普遍适用的,我在这里提到的大多数功能都将有利于我们整个联合生态系统。


这个故事首先在这里发表。