引用
原文:
作者:jose luis franconetti
翻译:陈云龙
在 2017 google i/o 大会的 keynote 演讲中,我们了解到,将在 android 上正式受到官方支持。消息一出,世界各地开发人员纷纷击掌欢呼——很多人认为 java 即将会被取而代之(老实说,我依然是 java 的爱好者)。
对 kotlin 的炒作是否合情合理呢?其实这也相当于 swift 语言的发展,令人兴奋的同时也有因这门语言并不成熟,所以很多开发者并没有使用它。
两年前我曾发誓倘若 google 不支持它,我也不会开始认真学习 kotlin。既然现在已经做了支持,那么我也有理由继续深入学习。
为了能快速学习这门新语言,我基于已有的开发技能并利用熟悉的语言(java 和 scala)来学习 kotlin。
第一印象
当阅读 kotlin 文档时,我注意到的第一个地方是它能编译字节码、javascript、native、而且它是由 jetbrains 开发的。下面让我们一起来攻克这门语言吧。
如果 kotlin 编译为字节码,则意味着它在运行时使用 jvm(java虚拟机)将字节码编译为机器码。
那么 javascript 呢? 事实上,它使用目标 ecmascript 5.1 将 kotlin 代码转换为 javascript。 虽然我不是 javascript 专家,但是可以查看以获取更多详细信息。
kotlin 的一个厉害的特性在于能够编译原生,并支持更多没有 jvm 的平台 - 现在,kotlin native 可以在 mac os、linux、raspberry pi 和 ios(通过在 mac 上交叉编译)上使用 llvm 生成可执行文件。 windows 平台尚不支持,但他们正在开发中。
我梦想的场景是:用 kotlin native 开发 android 和 ios 应用程序的所有业务逻辑,然后用特定平台语言(android = java / kotlin,ios = objective-c / swift)开发 ui。 kotlin native 仍然未成熟,所以在它成熟之前我必须等。
另一个人们比较关注重视的问题:
kotlin 与 java 能 100% 兼容吗?
查看就能知道答案:
这就是我此刻的反应:
但在我们真正深入了解这个特性之前,还有更多的细节值得我们去探索。
如果阅读过关于 kotlin 的文章,也会了解到它的特性:
- 不变性
- 代码量比 java 少
- 空指针安全性
- 功能编程性
下面我们详细分析一下这些特点。
不变性
与具有功能编程概念的所有语言一样,不可变性是主要的讨论要点之一。 那么在 kotlin 中它是如何工作?
变量可以是:
- 可变的:由关键字 var 表示;
- 不变的:由关键字 val 表示。
关键字 val 真的不可变吗?
不。当定义真正不可变的变量时,我们总是需要检查它是否满足两种不可变:
- 不可变的引用:一旦分配了引用,它就不能被分配给其它的引用。
- 不可变值:引用的值不能被改变。
fun foo() {
var mutable: int = 1
val immutable: int = 2
mutable = 2 // all ok
immutable = 3 // compile error
val collection = arraylistof(1, 2, 3) // immutable reference to a collection
collection.add(4) // adding a value to the collection, so we are modifying the values of the immutable collection.
}
那么 kotlin 有不可变的 collection 吗?
是的,它的确有。
你可以在不可变的 collection、map、set 等之间进行选择,因为该语言具有两种实现。如下所示:
fun bar(){
val immutablelist = listof(1,2,3)//引用和值都不可变
val mutablelist = mutablelistof(1,2,3)//引用不可变但值可变
}
代码量比 java 少
kotlin 有只保存数据的数据类,所以写所有 pojo 类可以用一种简洁的方式。
public class foo {
private int id;
private string name;
public foo(int id, string name) {
this.id = id;
this.name = name;
}
public void setid(int id) {
this.id = id;
}
public void setname(string name) {
this.name = name;
}
public int getid() {
return id;
}
public string getname() {
return name;
}
}
data class foo(var id: int, var name: string)
好的,此刻你肯定在想:为什么你使用 var(可变的)而不使用 val(不可变的)呢?
这是因为 java 中 foo 类从一开始就设置为可变。
在 kotlin 扩展中可以找到另一种编写较少代码的方法。其允许你在不修改源代码的情况下向类中添加方法/函数——告别使用 utils 类。 kotlin 团队已经使用了扩展的 jdk 类,如文件、io 和线程。
以下是标准库的示例:
fun file.deleterecursively(): boolean
fun file.foreachline(
charset: charset = charsets.utf_8,
action: (line: string) -> unit)
空指针安全性
如果使用 java 开发,那么在某些情况下,必须处理npe(null pointer exception),当忘记检查变量是否为 null 或者你没有预料到会有一个空值变量时,它会弹出 npe。
kotlin 对此有一个聪明的解决方法:默认情况下使所有类型不可为空。因此,编译器不会让你使用未初始化或不可空变量。但是通过运算符“?”你仍然可以使用可空类型。
以下是几个案例:
var foo =“foo”
foo = null //编译错误
var bar:string? =“bar”
bar = null
你可能会认为,不可为空的类型并不总是会被使用,因为有时它不在控制范围内,例如网络响应问题。
别担心,kotlin 包含一个“elvis 操作符”,通过这个简单的操作符“?”就可以表达典型的 if else null :
val foo:string = bar?:“foo”
所以告别 if else 表达式。
string foo = nullableresponse();
if (foo == null) {
// do something
} else {
// do something
}
最后一个关键是,你可以像 “?”一样使用 “!!” 操作符。它们区别在哪里?如果变量为 null,它将抛出一个nullpointerexception,所以请避免使用它!
java 互操作性
这个话题对我来说特别重要,因为我所有在 android 及后端开发中都是用 java 编写的。我也为此感到骄傲,所以我现在不想改变他们。
如前面所述,kotlin 与 java 是 100% 兼容的。
以下是使用 gson 和 retrofit 的一些示例:
@get("playlistitems")
fun playlistitems(@query("part") part: string,
@query("maxresults") maxresult: int, @query("playlistid") playlistid: string,
@query("pagetoken") pagetoken: string?, @query("key") key: string): call
val response: response = api.playlistitems(api.snippet_part, s.limit, s.playlistid, s.nextpagetoken, googleapikey).execute()
data class videoresourcenetwork(@serializedname("kind") val kind: string?,
@serializedname("videoid") val videoid: string?) : model(identifier = videoid)
在 mobile jazz,我们开发了 作为 ios 和 android 应用程序的远程日志记录服务。 android sdk 完全由 java 开发。 kotlin 同样可以开发——它可以在 kotlin android 应用程序中使用,因为与 java 可互操作。点击这里查看一个。
查看更多 内容。
结论
相信炒作——kotlin 是一种成熟的语言,为 java 开发人员提供了一种用于现代多平台应用的静态编程语言作为新起点。 java 8 是基于以前 java 版本的一个比较大的更新,但作为 android 开发者,我们只能使用 java 8 的一小部分功能。 kotlin 这点对我们来说更好。