未来的方向(由 Java 到 Kotlin 转变)

前言

Kotlin 非常适合开发服务器端应用程序,可以让你编写简明且表现力强的代码, 同时保持与现有基于Java 的技术栈的完全兼容性以及平滑的学习曲线: 表现力:Kotlin 的革新式语言功能,例如支持类型安全的构建器和委托属性,有助于构建强大而易于使用的抽象。
这是摘录 kotlin 推广网站介绍这个语言的一段话,intelliJ 作为一家最懂程序员的公司,推出了 kotlin 语言,在使用了一段时间后,我认为 kotlin 完成有资格配得上这段评价。
  1. 非常适合开发服务器端
  2. 表现力强
  3. 兼容 java
  4. 强大易用
通过这段时间对 kotlin 的探索和了解,我想表达一下自己对 kotlin 对个人以及对企业的转变意义的思考。
转变的第一步:学好 java 如果是一个对 java 语言不太理解的新手,不太建议一开始就深入的了解 kotlin 的运作方式。
kotlin 语法本身是对 java 中很多写法的封装,将 java 繁琐的写法转变成风格简练的 kotlin 写法,再将 kotlin 最终转化为 java class。
举一个简单的例子:
val str = user?.id

上面一段简短的 kotlin 语句,转化为 java,就是:
String str = null if (user != null) { str = user.id }

最终 kotlin 还是要回归到 java 之上。
java 本身支撑着庞大的生态,绝大多数的企业、开源库,都依然还在使用 java 开发,kotlin 能够做到与 java 本身最大程度的兼容,非常不容易。
在可预见的未来里面,java 依然是开发界的基石,有着不可代替的地位,因此作为一个真正的 kotlin 语言学习者,java 仍然是必修课程。
转变的第二步:用心理解 kotlin 对一个刚刚接触 kotlin 的使用者来说,对各种符号、关键字的运用,绝对是一大阻力。
如果想能够快速的明白 kotlin 真正的长处,那么一定要理解 kotlin 为什么要这样干?
kotlin 为什么要使用问号 "?" 编写 java 的过程,最普遍,最困难的就是在处理空指针问题。
一个系统的输入,要考虑健壮性,必须要定义好哪些变量是可以为空的,哪些变量又是不可为空的,当变量为空或者不为空,怎么去处理,上游代码给我的变量到底是不是空的。
相信只要是一个考虑问题比较全面的程序员,在编写代码时都会有这样的担心。
kotlin 的目的就是要消灭程序员的担心。
第一个目的是直接在源头控制好变量为空或者不为空的情况,这样程序员在每一步的编写代码时,能够安心的知道,我这个变量是肯定不会为空的,如果是为空的情况,我已经有了应对办法。
第二个目的,是对可能为空的变量,能够有非常友好、简单、可读性强的处理。
var userName = user?.name //当 user 不为空时将属性 name 复制给变量 userNameuser?.let { // 当 user不为空时,打印 name 属性的值 println(it.name) }user?.name?.let { // 当 user 以及 user.name 不为空时,打印 name 的值 println(it) } ?: println("name 为空") // 否则就输出 name 为空user?.name = "kotlin" // 当 user 不为空时,给属性赋值

在这里可以稍作一下停顿,思考一下在 java 处理这样的逻辑,需要以怎样的方式实现。
这种写法足以打动任何在 java 中多次处理空指针问题、或者在代码运行一段时间莫名其妙出现空指针异常的程序员。
kotlin 吸收 stream 如果是一个对程序写法有些追求的程序员,相信一定不会错过 jdk1.8 语法中的 stream 和 lambda。
当我希望将 List 中的 V 的某一个属性作为键转变为 Map 时,stream 已经提供了非常简洁的写法:
Map result = choices.stream().collect(Collectors.toMap(Choice::getName, Function.identity()));

java 已经非常简洁了,但是我每次希望做这样一种操作时,每次都在代码里面翻阅或者在网上搜索一遍用法。
在你使用了 kotlin 的做法后,相信你一定不会忘记它的写法:
val result = choices.map { it.name to it }.toMap()

对于复杂一些 stream 写法,你可能需要了解一番 java 如何向 kotlin 转变的,但是一般写法,只要求你删除 stream() 即可。
可以说,kotlin 完全吸收了 stream 的精髓,并且在这之上,青出于蓝而胜于蓝。
忘记 lombok 和 get set lomok 是 java 世界中不可忽视的补充力量,他让简单的 get set 定义不再被程序员需要,但同时它对类的直接修改,也让很多深入使用的程序员诟病。
归根结底还是由于 java 中的封装概念,即控制有限字段暴露。
于是在 kotlin 中,不再有 get set 的概念,只有赋值和直接获取,只需要利用 privatevalvar 这个几个关键字,就能够实现控制字段的可见范围。
val name: String? = null // 能够获取,不能修改var name: String? = null // 能够获取,能够修改private val name: String? = null // 不可获取,不可修改

同样在 spring boot 中常用的 lombok 注解 @RequiredArgsConstructor,用简单的构造函数直接生成字段就能够代替。
本身 lombok 的注解对 kotlin 代码就不生效,当转变使用 kotlin 时,移除 lombok 也是理所应当的事情。
少就是多 当你能够理解 kotlin 这三点主要的用途,并能够应用自如,那么你将节省至少三分之一的代码量。
在代码的世界里,少就是多,减少冗余代码,就是在为自己争取开发时间,就是问题出现的概率在减少,就是问题发生时排查的速度在提高。
这或许就是 kotlin 为程序员积累的经过时间沉淀下来的实实在在的经验。
转变的第三步:实践 当你成功的被 kotlin 简洁干练的语法所吸引时,在经过团队中进步人士的同意下,希望替换为 kotlin 时,请注意到,kotlin 完全兼容 java,不仅是 kotlin 努力的方向,责任更在使用者身上。
替换本身是愉快的,之前的代码在你的手中一行一行的缩短,一个个空指针判断在被替换为简洁的问号,但是风险也在一步步的提高,每进行一步替换都要做好充分的回归测试,谁也无法预料在自动 java 到 kotlin 的代码转换器,能否将逻辑推理的那么严谨。
在替换的过程中
  1. 你可会遇到 java static 的方法无法与 kotlin 很好的兼容
  2. java 接口中的 default 方法,无法在 mybatis 中的 mapper 接口中应用
  3. 各种意想不到的困难
但是在这些困难背后,解决完后的意义远大于困难本身,因此这一些都是值得的。
现代语言中的 kotlin 和 swift3 kotlin 语法的诞生不是偶然因素,而且代码在不断发展过程中的必然结果。
对比 kotlin 与 swift3,你会发现两者惊人的相似,或许是由于两个语言中的设计人员有一些重合。
但是这些重合的点,何尝不是一代代的人使用后积累下来的产物,总是会有人去不断的追求更高效、更方便、更快捷的开发方式。
这些方式也一定会被现代的语言不断吸收,这些优点终将会被保留,一直延续到新一代的计算机出现。
对未来 kotlin 的展望 希望 kotlin 语言能够被更多人和更多的企业接受。
对个人来说接受的不一定是非要使用 kotlin 开发,更多需要接受的是 kotlin 在设计过程汇总烁烁发光的思想方式,不断要求自己在原本的 java 技能上获取精进。
对企业来说,减少错误成本、降低错误率、降低开发时间,永远是效率为上,理解 kotlin 带来的价值并能够合理的加以应用,是重中之重。
【未来的方向(由 Java 到 Kotlin 转变)】同时也希望未来 kotlin 本身能够再进一层,不再以 java 作为中间语言,而是能够直接一步到位,拥有完全属于自己的编写、编译、运行的体系。

    推荐阅读