我为什么使用 Java

可能存在比 Java 更好的语言,这取决于工作需求。但我还没有看到任何能吸引我离开的东西。
208 位读者喜欢这篇文章。
Coffee beans

Pixabay. CC0。

我相信我从 1997 年开始使用 Java,那时 Java 1.1 刚刚问世后不久。 从那时起,总的来说,我非常喜欢用 Java 编程;尽管我承认现在,我更可能编写 Groovy 脚本,而不是用 Java 编写“严肃的代码”。

我之前使用 FORTRANPL/1Pascal,最后是 C。我发现 Java 有很多优点。Java 是我第一次重要的面向对象编程的实践经验。 那时我已经编程了大约 20 年,可以肯定地说我对什么重要,什么不重要有一些想法。

将调试作为关键语言特性

我真的很讨厌浪费时间去追踪由于我的代码不小心迭代到数组末尾而导致的晦涩的错误,特别是在 IBM 大型机上用 FORTRAN 编程的时代。 另一个不时出现的微妙问题是用一个四字节的整数参数调用一个需要两字节的子程序;在小端架构上,这通常是一个良性错误,但在大端机器上,高位两个字节的值通常(但并非总是)为零。

在这种批处理环境中进行调试也很尴尬 - 仔细研究核心转储或插入打印语句,这些语句本身可能会移动错误,甚至使它们消失。

因此,我早期在 MTS 上,然后在使用相同的 MTS 编译器在 IBM OS/VS1 上使用 Pascal 的经验,使我的生活变得轻松了许多。 Pascal 的 强类型和静态类型是其中的一大优势,而且我使用过的每个 Pascal 编译器都会对数组边界和范围进行运行时检查,因此可以在发生时检测到错误。 在 1980 年代初期,我们将大部分工作转移到 Unix 系统上,移植 Pascal 代码是一项简单的任务。

找到正确的语法量

但是,尽管我喜欢 Pascal 的所有优点,但我的代码很冗长,而且语法似乎有稍微掩盖代码的趋势;例如,使用

if … then begin … end else … end

而不是

if (…) { … } else { … }

在 C 和类似的语言中。 此外,有些事情在 Pascal 中很难做到,但在 C 中却容易得多。 但是,随着我越来越多地使用 C,我发现自己遇到了我在 FORTRAN 中犯的同样类型的错误 - 例如,运行到数组的末尾 - 这些错误未在原始错误发生时被检测到,而仅通过它们在程序执行后期产生的不利影响才被检测到。 幸运的是,我不再生活在批处理环境中,并且手头有很棒的调试工具。 尽管如此,C 还是给了我太多的灵活性,这对我自己不利。

当我发现 awk 时,我发现我对 C 有了一个很好的补充。 那时,我的很多工作都涉及转换字段数据和创建报告。 我发现我可以使用 awk 以及其他 Unix 命令行工具(如 sort、sed、cut、join、paste、comm 等)来完成相当多的工作。 本质上,这些工具给了我很多类似于文本文件的关系数据库管理器,这些文本文件具有面向列的结构,这是我们很多字段数据的传入方式。 或者,如果不是完全采用这种格式,则大多数时候都可以将数据从关系数据库或某种二进制格式卸载到面向列的结构中。

awk 支持的字符串处理、正则表达式关联数组,以及 awk 的基本性质(它实际上是一个数据转换管道),非常符合我的需求。 当遇到二进制数据文件、复杂的数据结构和绝对的性能需求时,我仍然会恢复使用 C;但是随着我越来越多地使用 awk,我发现 C 非常基本的字符串支持越来越令人沮丧。 随着时间的推移,我最终越来越多地只在必须使用 C 的时候才使用 C - 并且可能在其余时间里过度使用 awk。

Java 是合适的抽象级别

然后 Java 就出现了。 从一开始看起来就非常好 - 一种相对简洁的语法,让人联想到 C,或者至少比 Pascal 或任何其他早期经验更像 C。 它是强类型的,因此许多编程错误会在编译时被捕获。 它似乎不需要太多的面向对象学习即可上手,这是一件好事,因为那时我对 OOP 设计模式几乎不熟悉。 但即使在早期,我也喜欢其简化的 继承模型背后的思想。 (Java 允许单继承,并提供接口来丰富这种范例。)

它似乎还附带了一个丰富的功能库(“包含所有常用工具”的概念),该库在适当的级别上工作,可以直接满足我的需求。 最后,我发现自己很快就喜欢上了数据和行为都分组在对象中的想法。 这似乎是明确控制数据之间交互的一种好方法 - 比巨大的参数列表或对全局变量的无控制访问要好得多。

从那时起,Java 已经成长为我编程工具箱中的瑞士军刀。 我仍然偶尔会用 awk 编写一些东西,或者在 Linux 命令行实用程序(如 cut、sort 或 sed)显然并且准确地是解决手头问题的直接方法时使用它们。 但是,我怀疑我在过去 20 年里是否编写了 50 行 C 代码; Java 已经完全取代了 C,满足了我的需求。

此外,Java 也在不断改进。 首先,它的性能变得更高了。 它还添加了一些非常有用的功能,例如 try with resources,它可以很好地清理处理文件 I/O 期间错误处理的冗长且有些混乱的代码; 或者 lambdas,它提供了声明函数并将其作为参数传递的能力,而不是旧的方法,后者需要创建类或接口来“托管”这些函数; 或 streams,它将迭代行为封装在函数中,从而创建了一种高效的数据转换管道,以链式函数调用的形式实现。

Java 越来越好

许多语言设计者已经研究了如何从根本上改善 Java 体验。 对我来说,这些大多还没有引起我极大的兴趣; 同样,这更多地反映了我典型的工作流程,(远)少于这些语言带来的功能。 但是,这些进化步骤之一已成为我编程武器库中不可或缺的一部分:Groovy。 当我遇到一个需要小型解决方案的小问题时,Groovy 已成为我的首选解决方案。 此外,它与 Java 高度兼容。 对我来说,Groovy 填补了 Python 为许多其他人填补的相同空缺 - 它紧凑、DRY(不要重复自己)并且富有表现力(列表和字典具有完整的语言支持)。 我还使用了 Grails,它使用 Groovy 为非常高性能和有用的 Java Web 应用程序提供简化的 Web 框架。

但是 Java 仍然是开源的吗?

最近,对 OpenJDK 日益增长的支持进一步提高了我对 Java 的舒适度。 许多公司以各种方式支持 OpenJDK,包括 AdoptOpenJDK、Amazon 和 Red Hat。 在我一个更大、更长期的项目中,我们使用 AdoptOpenJDK 在 多个桌面平台上生成定制的运行时

有没有比 Java 更好的语言? 我确信有,这取决于您的工作需求。 但我仍然是一位非常快乐的 Java 用户,而且我还没有看到任何会威胁到把我带走的东西。

Chris Hermansen portrait Temuco Chile
自从 1978 年从不列颠哥伦比亚大学毕业以来,我很少没有某种计算机,自 2005 年以来我一直是全职 Linux 用户,从 1986 年到 2005 年是全职 Solaris 和 SunOS 用户,在那之前是 UNIX System V 用户。

8 条评论

你好,Chris! 令人印象深刻的简历和精彩的撰写。 感谢分享。

我建议您看看 Kotlin。 Kotlin Koans 是一种不错的入门方式,kts(Kotlin 脚本)可能会取代您的 Groovy。 我真的很喜欢 Kotlin 非常强大的类型系统,同时与 Java 和 Groovy 非常相似(只是翻转的声明需要几天才能习惯)。

感谢您的评论,TWiStErRob。

我研究过 Kotlin,但到目前为止它并没有“打动我”。也许有一天会的! Groovy 感觉就像我一直希望 Python 给我的感觉,并且它引导我学习了 Grails,这让我对 Java 中所有美好的事物(例如 Spring)有了极大的欣赏。

无论如何,听起来你对 Kotlin 很感兴趣,所以我恳请你写一篇或多篇关于它的文章,发表在 opensource.com 上!

回复 ,作者:TWiStErRob (未验证)

很久以前我就决定使用 php 和 html,因为你无法在浏览器中看到源代码。你只能看到结果。我知道有很多方法可以防止这种情况,但作为一名新手网络程序员,这似乎是保持数据库数据安全的明智之举。

感谢您的评论,MJH。据我所知,没有任何服务器端 Web 框架会在他们传递给浏览器的 HTML 中公开源代码(我说的是像 PHP、Grails、Rails、Django...这样的东西)。有些不需要服务器上有源代码,而是执行字节码或本机代码。例如,对于 Grails(我最熟悉的),开发人员在开发机器上创建一个 .war 文件(Java .class 文件和 HTML、CSS、图像等),然后将其放在服务器上,应用程序服务器(例如 Tomcat)解压缩它并提供服务。

回复 ,作者:MJH (未验证)

换句话说,你喜欢 Java 的原因和我喜欢 Ada 的原因是一样的。强类型和语法大大减少了调试时间。此外,形式验证(使用 SPARK,Ada 的一个子集,与 Apache 无关)可以帮助您减少错误数量。

我只是更喜欢冗长的语法“if .. then .. else .. end if”,而不是紧凑的基于 {} 的语法。

感谢您的评论,Riccardo。就我的经验而言,Java 中的强静态类型是一个巨大的优势。我同意我们在喜欢简洁还是冗长语法方面存在差异,我只想说,各有所爱。

对我来说,另一个产生巨大差异的是 Java 附带的所有好东西。例如,回到“美好的 Pascal 时代”,那时我可用的内存非常有限,我会通过创建一个中间查找数组,将代码值(例如在 1-500 范围内)转换为“出现索引”(例如在 1-25 范围内),来构建基于代码值的累加器。该出现索引将用于索引到堆结构的指针数组中以进行累积。当然,这种类型的结构很容易不小心使用代码值而不是代码值的索引来在指针数组中查找,这将导致各种难以追踪的错误。

Awk 的关联数组,以及后来的 Java 的全套 HashMaps,完全解决了这种问题。当然,到那时,我的内存限制也不再那么成问题了。 HashMap 与泛型提供的类型检查相结合,进一步有助于在编译时检测错误。

所以,不是很熟悉 Ada 带来了什么样的“电池”,我不确定我们是否完全站在同一页面上!但无论如何,再次感谢你的来信,我邀请你考虑为 opensource.com 撰写一篇题为“我为什么使用 Ada”的文章!

回复 ,作者:rpr

我完全同意 - 我于 1996 年开始使用 Java,并且没有回头,尽管我仍然有一些重要的 C++ 遗留代码库,我需要在极少数情况下维护它们。

新语言一直在不断涌现(告别 Ruby,希望理智最终能到达那些认为在服务器端编写 JavaScript 是个好主意的人)。

其中一些语言说,例如,“我可以在新的 XYZ 语言中完成这种令人难以置信的文本操作,并且最终比在 Java 中实现相同的文本操作少输入 27% 的字符。”

为了回应这些说法,我说“做得好,这是你的慢高尔夫鼓掌:当我的开发者工作变成 97% 的时间都在输入代码并以奇怪的方式操作文本时,我将切换到你新的、当月的 XYZ 语言”。

我认为黑客倾向于将编码视为主要是一种打字练习,因此节省击键次数似乎是一种生产力的胜利。对于他们来说,像需要为任何变量或参数输入类型规范的类型安全之类的东西,只是令人讨厌的额外击键,没有真正的好处(LoL!)。

相反,我倾向于花大量时间评估我正在构建的 OO 模型的不同选项,然后才开始输入任何内容 - 与我“拼凑头脑中想到的第一件事”相比,花时间在白板上草拟多个实现方案可以节省数天、数月、数周的时间。

感谢您的评论,Golman。总的来说,我同意你的看法 - 在开发者的世界里,对闪亮的新事物有很多(也许是太多)的欣赏。

话虽如此,我相信简洁是有价值的,尤其是在“不要重复自己 (DRY)”中表达的。对我来说,Java 8 及更高版本中的函数式接口对于代码维护者和开发人员来说都是一个巨大的好处,只需减少由“here”对象产生的样板代码,这些对象的唯一目的是为单个函数提供实现。 减少打字的明显事实有点顺便;真正的好处是代码更紧凑和可读,并且在不被大量“如何”包围的情况下,“什么”更加清晰可见。

从我的角度来看,整个增强集合是另一个很好的例子,内部迭代器和 lambda 是非常好的东西。

我的 Java(和 Groovy)函数式 fu 仍然非常初级。 例如,如果我有一个输入文件,其中每行都包含几个不同的键值对要加载到几个不同的 map 中,我不知道有什么方法可以仅处理一次并将所有 map 作为函数式结果传递。 也许它在那里,我只是还没有看到它; 但在 Groovy 中,我倾向于做大部分这类事情,我发现自己声明了所有的 map,然后使用“each”来迭代文件,并按照我的想法分配 map1[key1] = value1,map2[key2] = value2 等。

100% 同意在设计概念上花费时间。 我发现现在白板的替代方案是用 Groovy 进行原型设计。 我不是一个非常视觉化的人,所以缺乏图表不会让我感到困扰。 在我确定一个似乎朝着良好方向发展的原型之前,我可能会制作几个原型; 而且我经常使用原型设计作为测试相对性能的借口。 涉及 SQL 时情况也是如此。 但我怀疑这可能更多地表明什么适用于我发现自己正在解决的各种问题,而不是一个普遍规律。

无论如何,再次感谢您周到的评论。

回复 ,作者:Golman (未验证)

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.