写点什么

从 Java 到 Scala,再到 Kotlin,java 面试知识点太多

用户头像
极客good
关注
发布于: 刚刚
  • Stream API。流的引入简化了日常开发中的集合操作,并赋予了更强大的业务表达能力,并增强了代码的可读性;

  • Optional 类。为消除 null 引用所带来的 NullPointerException 问题在类型层面提供了一种解决思路。 这一次的发布在 Java 社区引来了不同寻常的反响,因为 Java 程序员开始感受到另外一种编程范式所带来的全新体验—也就是所谓的函数式编程。拥抱函数式也为 Java 的发展指引了一个很好的方向。

Java 未来会是什么样子

2016 年 11 月在欧洲最大的 Java 峰会上,Oracle 的 Java 语言架构师—Brian Goetz 分享了关于 Java 这门语言未来发展的演讲。本次会议最大的收获,就是探索了未来 Java 可能支持的语言特性,它们包含了:


  • 数据类

  • 值类

  • 泛型特化

  • 更强大的类型推导

  • 模式匹配


以上的语言特性,对于初尝函数式编程甜头的 Java 开发者而言,是十分值得期待的。它们可以进一步解放 Java,让开发工作变得更加高效和灵活。比如,一旦 Java 支持了数据类,我们就可以用非常简短的语法来表示一个常见的数据对象类,就像这样子:


public class User(String firstName, String lastName, DateTime birthday)


而用如今的 JavaBean,则意味着好几倍的代码量,这一切都让人迫不及待。与此同时,或许早有 Java 程序员开始了 JVM 平台上另一种语言的研究。这门语言已支持了所有这些新的特性,并在设计的一开始,就集成了面向对象和函数式两大特征,它就是 Scala。

Scala 的百宝箱

Scala 是洛桑联邦理工大学的马丁(Martin Odersky)教授创造的一门语言。他也参与了 Java 语言发展的研究工作,Java 5 引入泛型就是他的杰作。事实上,在 Java 刚发布的时候,马丁教授就开始了 Java 的改良工作—他在 JVM 平台探索函数式编程,发布了一个名为 Pizza 的语言,那时就支持了泛型、高阶函数和模式匹配。


然而,在随后的探索过程中,他渐渐发现 Java 是一门具有硬性约束的语言,在某些时候不能采用最优的方式来实施设计方案。因此,他和他的研究伙伴决定重新创造一门语言,既在学术上合理,同时也具备实用价值,这就是 Scala 的由来。

学术和工业的平衡

Scala 是一门非常强大的编程语言,正如它名字(Scalable—可拓展)本身,用 Scala 编程就像拥有了哆啦 A 梦的口袋,里面装满了各种编程语言特性,如面向对象、函数式、宏。


Scala 不仅在面向对象方面进行了诸多的改良,而且彻底拥抱了函数式。因此 Scala 也吸引了函数式编程社区很多厉害的程序员,他们将函数式编程的思想注入到了 Scala 社区,如此将使用 Scala 进行函数式编程提高到了新的高度。


由于 Scala 设计者学院派的背景,以及它某些看似“不同寻常”的语法,它在发展早期(甚至现在)经常被描述为“过于学院派”,以至于马丁教授在某次 Scala 大会的演讲时,自嘲“Scala 真正的作用是将人引向了 Haskell”。


然而,真实的 Scala 却是在不断地探索学术和实用价值两方面的平衡。不可否认的是:


  • Scala 已经成为大数据领域的热门语言,明星项目 Spark 就是用 Scala 开发,还有很多其他知名的项目如 Akka、Kafka;

  • 越来越多的商业公司如 Twitter、PayPal、Salesforce 都在大量使用这门语言。


另一方面,Scala 也确实是一门有着较陡的学习曲线的语言,因为它强大且灵活,正如马丁教授自己所言,Scala 相信程序员的聪明才智,开发人员可以用它来灵活选择语言特性。但学术和工业的平衡始终是一个难题,与 Java 严格标准相比,Scala 的多重选择也常常让人吐槽它复杂。

复合但不复杂

那么,Scala 真的复杂吗?我们不知听了多少次类似这样的抱怨。在搞明白这个问题之前,我们需要先弄清楚到底什么是“复杂”。在英文中,复杂一词可以联想到两个单词—complex 和 complicated。实际上它们的含义截然不同,更准确地说,complex 更好的翻译是“具有复合性”。 Nicolas Perony 曾在 Ted 上发表过一次关于“复合性理论”的演讲。


什么是复合性?复合并不是复杂。一件复杂的事物是由很多小部分所组成的,每一部分都各不相同,而且每一部分都在这个体系中有其自身的确切作用。与之相反,一个复合的系统,由很多类似的部分所组成,而且(就是因为)它们之间的相互影响,才形成了一种宏观上一致的行为。复合系统含有很多相互动的元素,它们根据简单的、个体的规则行动,如此导致新特征的出现。


马丁教授同样发表过一篇名为《简单还是复杂》的文章,表达过类似的观点。如果对搭积木这件事情进行思考,摩比世界提供固定的方案,而乐高提供了无穷的选择。然而,前者的零件种类数量比后者要多得的。类似的道理,编程语言可以依靠功能累加来构建所谓的语法,同样也可以通过简单完备的理论来发展语言特性,在马丁教授看来,Scala 显然属于后者,它并不复杂,而且非常简单。

简单却不容易

事实上,函数式编程最明显的特征就是具备复合性。函数式开发做的最多的事情,就是对所需要处理的事物进行组合。如果说面向对象是归纳法,侧重于对事物特征的提取及概括;函数式中的组合思想则更像是演绎法,近似数学中的推导。


然而,“简单”的哲学也带来了相应的代价:


  • 这是一种更加抽象的编程范式,诸如高阶类型、Typeclass 等高级的函数式特性虽然提供了无比强大的抽象能力,但学习成本更高;

  • 建立了另一种与采用 Java 面向对象编程截然不同的思维模式。这种思维方式上的巨大差异,显然是一个极高的门槛,同时也是造成 Scala 令人望而却步的原因之一。


Scala 在选择彻底拥抱函数式的同时,也意味着它不是一门容易的语言,它无法成为一门像 Java 那样主流的编程语言。事实上,即使很多人采用 Scala 来进行开发,也还是采用类似 Java 的思维模式来编程,换句话说,Scala 依旧是被当做是更好的 Java 来使用,但这确实是当今主流编程界最大的诉求。


在这种背景下,Kotlin 作为一门 JVM 平台上新兴的编程语言,悄悄打开了一扇同样广阔的大门。

Kotlin—改良的 Java

2010 年 JetBrains 开始了创造 Kotlin 的想法。关于大名鼎鼎的 JetBrains,想必是家喻户晓,知名的 IntelliJ IDEA 就是他们的产品之一。拥有为各种语言构建开发工具经验的 JetBrains,自然是对编程语言设计领域最熟悉的一群人。当时,一方面他们看到了 C#在.NET 平台上大放异彩,另一方面,Java 相比新语言在某种程度上的滞后,让他们意识到了改良 Java 这门主流语言的必要性。


JetBrain 团队设计 Kotlin 所要面临的第一个问题,就是必须兼容他们所拥有的数百万行 Java 代码库,这也似乎正好代表了 Kotlin 基于整个 Java 社区所承载的使命之一,即需要与现有的 Java 代码完全兼容。这个背景也决定了 Kotlin 的核心目标,就是为 Java 程序员提供一门更好的编程语言。

Kotlin 的实用主义

Kotlin 常常被认为是一门非常近似 Scala 的语言。的确,它们的诞生都源于 Java 语言的改良,同时都在面向对象和函数式之间建立起了多范式的桥梁。不可否认的是,Kotlin 确实从 Scala 身上借鉴了许多,就连它的创作团队也表示过:“如果你 Scala 用的很开心,那么你并不需要 Kotlin。”


然而,Kotlin 与 Scala 的设计哲学又十分不同。Kotlin 并没有像 Scala 那样热衷于编程语言本身的研究和探索。相反,它在解放 Java 的同时,又在语言特性的选择上表现得相当克制。


我们说过,Scala 旨在成为一门程序员梦想中的语言,它包含了所有你想拥有的语言特性。而 Kotlin 更加立足现实,它现阶段仍没有宏,也拒绝了很多所谓的高级函数式语言特性。但它在 Java 的基础上发展了很多改善生产力的语言特性,如数据类、when 表达式(一定程度上的模式匹配)、扩展函数(和属性)、可空类型等等,而且它似乎偏好语法糖,比如 Smart Casts,


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


因为这可以让编程人员在工程中的开发变得更加容易。


可以看出,Kotlin 的自我定位非常清晰—它的目标就是在应用领域成为一门实用且高效的编程语言。如果说 Scala 的设计理念是 more than Java(不仅仅是 Java),那么 Kotlin 才是一门真正意义上的 better Java(更好的 Java)。

更好的 Java

如果你用 Kotlin 开发过业务,很快就会意识到它相较于 Java 的语法,显得更加简洁、高效,比如 Kotlin 做了这些改良:


  • 极大程度上实现了类型推导,而 Java 在 SE 10 才支持了局部变量的推导;

  • 放弃了 static 关键字,但又引入了 object,我们可以直接用它来声明一个单例,作为比较 Java 则必须依靠构建所谓的“单例模式”才能等效地表达;

  • 引入了一些在 Java 中没有的“特殊类”,比如 Data Classes(数据类)、Sealed Classes(密封类),我们可以构建更深程度上的代数数据类型,结合 when 表达式来使用。


但可能你会问,以上 Kotlin 的特性,Scala 也有,能否可以说前者只是后者的一个子集。这种表述其实是不恰当的。其实,Kotlin 在致力于成为更好的 Java 的道路上,不仅仅是依靠这些新增的语言特性,它在兼容 Java 方面的设计,做了大量的工作,比 Scala 走的更远。


首先,从语言命名上就可以看出 Kotlin 在严格遵循 Java 的先例,它们都采用了岛屿的名字。


Java 的名字来源于印度尼西亚瓜哇岛的英文名称,而 Kotlin 是俄罗斯圣彼得堡附近的一个岛屿。


其次,虽然都是兼容 Java,Scala(最近的几个版本)必须要求 Java 8,而 Kotlin 则可以跟 Java 6 一起工作,这也是后者在 Android 上更加流行的原因之一。


另外,Kotlin 并没有像 Scala 那样在语法的探索上表现得“随心所欲”,Java 程序员在学习 Kotlin 新语法特性的同时,依旧可以保留更多原有的习惯。举个例子,在 Scala 中,一切皆有类型。所以大部分时间,我们都用等号来定义一个 Scala 的函数。函数体最后一个表达式的值就是这个函数的返回类型。


def foo(x: Int) = {val y = x + 2x + y}


没错,Scala 舍弃了 return 关键字。在 Kotlin 中,它也引入了使用单行表达式来定义函数的语法,不需要用 return 来返回结果值。


fun foo(x: Int) = x * 2 + 2


然而,大部分情况下,我们还是可以采用类似 Java 的方式来定义一个函数,如:


fun foo(x: Int): Int {val y = x * 2

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
从 Java 到 Scala,再到 Kotlin,java面试知识点太多