James Gosling 本人出生于加拿大,是一位计算机编程天才。 1977年获得加拿大卡尔加里大学计算机科学学士学位,1983年获得美国卡内基梅隆大学计算机科学博士学位。毕业后到Sun工作,这就是Java多于。
近日,外媒Evrone的软件工程师、技术编辑Grigory在线对话了Java之父James。 在采访中,詹姆斯提出了很多观点。 他认为:“软件的可靠性要求越高,静态类型语言越有帮助。” 宏,又爱又恨 Lombok,又爱 Lisp,等等。
关于现代编程语言是如何构建的
Grigory:作为软件开发人员和软件顾问,我们尝试在俄罗斯组织 Python、Ruby、Java 和 Go 社区。 您在 Java 方面的经验和工作可以很好地帮助开发人员。 通过这次采访,我们希望能帮助其他开发者解决行业中的基本问题。
一些语言java用什么软件编写,如 Go,没有类和继承,而其他语言则尝试使用 Rust 等功能。 作为语言设计者,您认为构建编程语言的现代通用、合理的方法是什么?
James:我可能会继续使用类,类对我的编程工作非常有用。 C 中有一些宏,这是非常糟糕的,因为宏不是语言的一部分,不应包含在内。 Rust 的人们正试图让宏恰到好处。
对于其他语言,比如 Lisp 家族,人们总是试图更灵活地应用它们。 他们有一种定义几乎完全独立于语义的语法的方法。 在大多数语言中,语法和语义密切相关。 我写过很多 Lisp,而且我真的很喜欢使用 Lisp 程序。 有一些语言可以让你以不同的方式做到这一点,例如在 Groovy 中你可以直接使用 AST,Rust 有一些语法集成的宏。 但我总觉得还有一个问题:我还能做什么?
Lisp 对代码片段进行操作以生成新代码,这就是人们在 Java 世界中的做法。 虽然看起来很低级,但很受欢迎。 可以使用注释的组合来生成几种不同语言的字节码,这是非常强大的。 它会给你意想不到的惊喜,比如在 Jackson 中,它通过计算序列化器来扩展性能。
一方面,这是一项非常强大的技术,另一方面,又很难掌握。 这项技术充满了可能性,但可能性是有限的。 我对 Lombok 既爱又恨,因为它添加了一大堆 Java 特性,这些特性很好,但另一方面也显示出弱点。 JCP的社区功能日渐式微,我离开好几年了,虽然有些事情可以做,但也只能停留在纸上谈兵。
Grigory:这就是为什么我们宁愿听取您创建该语言的经验,也不愿听取一些 Java 增强建议。 五年前,我试图操纵一些 Java 字节码。 我发现用它创建领域特定语言有点困难。 但是使用 Ruby,这就容易多了。 Evrone 有许多精通 Ruby 的开发人员。 Ruby 开发人员很棒,但他们需要多年的培训才能真正掌握 DSL 的魔力。
James:像代码片段算法这样的特性在 Java 中很尴尬,因为 Java 总是试图编译机器码,而 Ruby 几乎总是解释性的。 如果您想同时获得超能力和终极性能,这一切都会变得困难。
那些重大变化呢?
Grigory:最近,我们采访了 Ruby 的创造者 Yukihiro Matsumoto,他尝试了最新的 Ruby 3.0 版本,试图在不破坏更改的情况下发布它。 我知道 Java 一直对“不破坏更改”保持谨慎。 让所有语言完全兼容地进化是否合理? 或者此方法是否仅适用于特定语言,例如 Ruby 或 Java?
James:这几乎完全取决于开发者社区的规模。 每一个重大变化都会给开发者社区带来痛苦。 如果您没有很多开发人员,那么重大更改并不是一个大问题。
除此之外,您还必须权衡成本效益。 如果你做一个破坏性的改变,它会增加你的工作量,但它也可能带来一些好处。 但是,如果你只是把下标运算符从方括号改成圆括号,对你没有任何好处,只会增加麻烦。
在 JDK 9 中,有一个罕见的破坏性变化:如果使用隐藏 API,封装机制将被破坏。 人们打破封装边界,用非常规的方式,用不该用的东西,变化是痛苦的。 但是,一旦我们彻底改变,平台就有了更大的创新空间。 这种变化下,平台可以划分,可以自定义包,Java运行环境会更小。
另一个并发症:当你遇到一个错误时,人们会为它做变通办法,如果你修复了这个错误,变通办法就会失效。 在Java世界里,确实有这样的例子,我们要么不修复bug,要么引入修复bug的方法,甚至体现在硬件上。
静态类型检查器呢?
Grigory:当我 25 年前开始我的软件开发生涯时,我写了很多 C 和 C++ 代码。 几乎每个月都会遇到误报。 调试这些错误很痛苦。 但是现在,我看到许多工具集成到我们的工作流程中,例如静态类型检查器。 现代开发人员使用 IDE,例如 NetBeans、IntelliJ IDEA,甚至 Visual Studio。 他们编写源代码,编写静态类型检查器解析器,构建抽象语法树,检查它们,并在文本编辑器中标记错误。 这些技巧不仅适用于静态类型语言,也适用于动态类型语言,并且在 Python、Ruby 和 TypeScript 中可用。
您对静态类型检查器有何看法? 它们是帮助人们编写更好的程序,还是需要在语言语法中添加更多东西?
詹姆斯:我都同意。 我非常喜欢带有静态类型系统的语言,因为它们为静态类型检查器和 IDE 提供了框架。 作为一名高级软件工程师,发现那些奇怪的bug是最耗时的事情。 为了减少在这方面的时间浪费,我会尽量避免bug的出现。 因此,我非常喜欢 IDE,它可以提供一种减少错误的方法。 但是,动态类型语言很少有解决这个问题的框架,因为它们可能无法判断所有类型,只能靠猜测。 Java 等强类型语言为类型检查器提供了更严格的框架。 在另一个层面上,甚至可以执行自动定理证明。 像 Dafny 这样的系统,它有一个非常复杂的定理证明器。 所以如果你想建立一个加密算法,你将能够在数学上证明它。 这听起来有点夸张,但对于某些代码来说,它确实很有用。
很大程度上取决于你的目标是什么。
这是开源软件的黄金时代吗?
Grigory:让我们谈谈商业和行业的发展。 我从未做过机器人,但我曾在大型开发公司工作过,如果将今天与 20-25 年前进行比较,我们会看到像 GitHub 这样的社交编码平台得到大公司的支持,它们帮助个人进行开源开发开发人员和企业软件开发人员。 那么,这是开源软件的黄金时代吗? 你怎么认为?
詹姆斯:我不知道。 这个问题关乎未来。 “这是黄金时代吗?” 背后的意思是,未来是在走下坡路吗? 如果现在是黄金时代,未来不就是黄金时代吗?
我认为我们一直在通往黄金时代的路上,仍在进步。 现在,我们仍然存在各种安全问题和网络攻击,所以我不保证这是一个黄金时代。 如果有一种方法可以结束网络安全风险,那就太好了。 现在是一个非常好的时机,但它可以更好。
为什么有的语言不用JIT?
Grigory:您使用 JIT(即时编译)创建了 Java 和 JVM。 JIT 在保证高速度的同时保持高级语法。 许多语言紧随其后,例如 C# 和 JavaScript。 其他语言,如 Python、Ruby、PHP,有可选的 JIT,但不太常用。 很多主流语言为了速度也不用JIT。 为什么不是所有的语言都使用JIT? 他们不想为软件开发人员提供更快的速度吗?
James:如果开发人员想要获得性能改进,使用静态类型语言非常有用。 通常,人们给一种语言添加注解,你就得到了像 TypeScript 这样的语言,它本质上是带有类型注解的 JavaScript。 JavaScript的本质是Java,只是去掉了类型声明。 所以 TypeScript 本质上是具有替换语法的 Java。
在Python这样的语言中,通常只有一种数值,那就是双精度浮点数。 没有真正的整数,没有字节和 16 位整数这样的东西。 如果是双精度浮点数和单精度浮点数,概念认知的过程会比较复杂,但是一定要掌握数值分析。 许多软件工程师对数值分析几乎一无所知,所以他们就放弃了。
如果您是使用 Python 的物理学家,那么精度对您来说至关重要。 如果您需要在内存中容纳一个非常大的数组,则单精度和双精度或 8 位整数之间的差异非常重要。
在我的一生中,我参加了很多数值分析课程,我对数值分析感到不知所措,以至于我不得不专注于数值分析。 具体问题具体分析,大部分使用脚本语言的人都不关注这类问题。 很多人并不关心具体的性能和数字,他们关心的是:“够快吗?” 性能是一个布尔值,对于某些人来说,它更像是改装赛车,如果你的车能多开两到三英里,你获胜的可能性就越大。
Grigory:几个月前,Ruby on Rails(一种流行的 Web 框架)的作者 David Heinemeier Hansson 提到,在他的云计算应用程序开发中,性能基本上是由缓存、消息队列、存储等来控制的。相关方,开发语言的影响不得超过15%。 他指出,无论 Ruby 有多“慢”,这都无关紧要,因为即使 Ruby 快 100 倍,将 15% 变成 1% 也不会改变任何事情。
James:详细分析你的任务类型。 如果你的任务主要是网络、数据库等,而你一直在做 RPC,那么第一步就是质疑那些 RPC 是否值得。 微服务很好,但它们比方法调用慢一百万倍。 想想这意味着什么。
对于大多数人来说,他们可以通过清晰的大规模架构获得更多性能。 但对某些人来说,所有细节都很重要。 如果知道高并发的重要性,就知道它可以同时驱动上千个进程,进行大规模的计算; 如果你是做数据库或者存储服务的,你会很在意这些细节。 所以这一切都取决于手头的任务。
关于现代异步/等待方法
Grigory:许多语言都采用协程和异步/等待方法来处理网速慢等问题。 此方法已添加到 Python、Ruby、JavaScript 和其他语言中。 但是这种方法在线程中并不是万能的,而且比较复杂,有时还会拖慢软件的速度。 那么您如何看待这种现代异步/等待方法? 这是处理网络的好方法,还是我们误用了它,我们需要寻找其他方法?
詹姆斯:还是要看实际情况。 协程是完美的,它起源于 60 年代。 第一个使用协程的语言是 Simula 67。Simula 是一个很好的语言,它没有线程,但是它有协程,但是他们做协程的方式看起来很像线程。 协程完全避免了并行中的一些难题。 对我来说,协程有一个问题:它们不允许多个处理器真正并行。 所以我已经很久没有使用协程了。
所以人们更加关注那些真正具有并行性的语言,比如Erlang和Java。
使用 Java 中的 ConcurrentHashMap 可以做很多事情。 如果你在做多协程操作并且没有足够的处理器,一旦你使用基于协程的语言并使用多个处理器,你最终只会饱和一个处理器。 使用多个处理器也是不得已的办法,毕竟世界上已经没有单位处理器了。 一切都有很多核心,如果你想同时使用所有计算机解决一个问题,你只需要克服多线程固有的复杂性。
还有风格问题。 透明的控制反转一直在发生,你只能被动接受。 这会让你的语法看起来很像线程,但也意味着你会在真正的线程中遇到一些问题。 比如输入语句“a = a + 1”,就知道这个操作不会被中断,所以不需要同步。 但在其他情况下,它变成了面向事件的风格。 在运行过程中,需要插入一个事件处理器来处理后续的问题。 这是 JavaScript 的主要风格。 这还不错,但似乎有点笨拙。
当我在 70 年代初第一次接触 Simula 时,我发现它非常灵活,在编码过程中计算几乎是独立的。 作为一个概念模型,它更清晰。
第一语言的选择
Grigory:我想问一个非技术性的问题,在您看来,对于刚刚起步的软件开发人员,或者研究生和大学生,他们应该选择哪种语言作为他们的第一语言?
James:我回答这个问题可能有点偏见,毕竟 Java 已经成功运行了这么多年。 我学习的第一种编程语言是 PDP-8 汇编代码,然后是 Fortran。 人们可以学习任何语言,有些人更容易接受,但这在很大程度上取决于一个人的最终职业道路。 如果你想成为一名软件开发人员,你想构建大型、高性能的系统,运行在 JVM 上的语言是最值得学习的,比如 Scala 和 Kotlin,Clojure 很有趣。 如果你是物理专业的,Python 是一个不错的选择。
你选择哪种语言真的不重要,很多人只是坚持他们学习的第一门语言,如果你能让人们一遍又一遍地学习语言,那绝对是最好的事情。 我认为每所大学都应该为学生开设“比较编程语言”课程。 用五种不同的编程语言做作业会加快学习过程,他们会看到语言之间的差异真的没有那么大,也会让他们自己思考哪种语言更好。 很久以前,我上了一门课,每项作业都使用了最不合适的语言,例如,Cobol 中的数值计算和 Fortran 中的符号操作。 令人惊讶的是,我仍然得到了 A。
“模式匹配”呢?
Grigory:下一个问题是关于模式匹配的。 最近,它已与 Python、Ruby 集成,并针对不同的语言提出了建议。 我们查阅了开发人员白皮书,发现我们并不完全确定模式匹配在现代高级语言中的作用。 您如何看待这种模式匹配的思想适用于 Java、Python、Ruby 或其他高级语言? 我们真的需要模式匹配,还是一种特殊情况的特定用法?
James:对于新手来说,我认为编程语言中的“模式匹配”这个词是有误导性的。 当我听到“模式匹配”这个词时,我会想到正则表达式。 Simula 有检查语句,检查语句与许多模式匹配语句几乎相同。 inspect语句是一个case语句,其中case标签是类型名,可以执行:
Inspect P
When Image do Show;
When Vector do Draw;
所以你可以把它看成一个case语句,用case来处理类型,这是大多数模式匹配语言的建议。 就个人而言,我喜欢它,尤其是响应 C 的隐形演员表。 在像 C 这样的语言中,往往需要进行类型转换。 如果你做“inspect P When Image P do P”,那么在case语句的主体中,P就是switch标签的类型,这会让一切变得容易很多。 我真的很喜欢 Simula 中的 inspect 语句。 我同意所谓的“特殊情况”,如果它被称为“模式匹配”,但它不如正则表达式,它会产生误导,就像虚假广告一样。 但除此之外,我仍然认为它很强大。
所有的语言都可以联系在一起吗?
格里戈里:最后一个问题。 俄罗斯软件开发人员为 JetBrains 和 Kotlin 的开发感到自豪。 Kotlin、Clojure 和 Scala 等语言在您创建的现有代码的 Java 虚拟机、库、框架和生态系统中蓬勃发展。 但是这些语言都面临挑战吗? 这些语言可以联系在一起吗? 当尝试使用不同的语法在 Java 上执行热交换操作时,有人会遇到什么困难?
詹姆斯:这取决于你的目的是什么。 Java 虚拟机内置了很多安全性和可靠性概念,主要与内存模型的完整性有关,比如指针之类的东西,所以你不能伪造指针。 对于C,如果你没有造假的能力,你就做不到。 如果尝试在JVM上实现C语言,配置严格安全的虚拟机,有些功能是无法实现的。 但是有些人构建的虚拟机没有严格的安全模型,也没有内存分配模型。 如果要实现 C 和 Kotlin 之间的互操作性,就必须放弃一定程度的安全性和可靠性。 这取决于您的选择。
在Java早期java用什么软件编写,我的原则是:不想调试内存损坏问题。 我在内存崩溃上浪费了太多时间,这可能会占用你几天的时间。 我真的很讨厌追踪内存损坏错误。 虽然每个人的喜好不同,有些人可能会觉得花时间做这件事是值得的。 其他人喜欢使用 vi,这是 70 和 80 年代的伟大编辑器。
Grigory:内存安全模型真的很重要,它提供了一些东西,但也造成了一些限制。 非常感谢,詹姆斯!
结语
看完Java之父的访谈,你有哪些收获和感悟? 对您来说,哪种语言是您的母语?
本文由原作者授权,CSDN翻译。 转载请注明出处! 原文链接:
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。