你的浏览器不支持canvas

牛马的一生不该是十四亿的重复,而应该是各有各的精彩。

Kotlin:从对比Java开始

Date: Author: codexu

本文章采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。

介绍

今年初,甲骨文再次对谷歌所谓的Android侵权使用Java提起诉讼,要求后者赔偿高达90亿美元。随后便传出谷歌因此计划将主力语言切换到苹果主导的Swift,不过这事后来没了跟进。

但后来,在Google IO 2017上,谷歌宣布Kotlin成为Androi官方开发语言.

Kotlin由JetBrains公司开发,于2010年首次推出,次年开源。它与Java 100%互通,并具备诸多Java尚不支持的特性,下一版的Android Studio(3.0)将提供支持。

特点

谷歌选择Kotlin当然不仅仅是因为与甲骨文的官司,Kotlin做为一种编程语言还是有很多长处与特点的.

如标题所讲,接下来我们来将Kotlin与Java做些对比

POJO

java:


public class User {
   private long id;
    private String userName;
    private String pwd;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

这是一个简单的POJO,属性+设置+获取,三个属性的类写了将近30行代码

Kotlin:

data class User(
var id: Long,
	var uerName: String,
	var pwd: String)

在Kotlin中,4行代码,包括了属性,设置,获取,不仅如此,它还包含了equals(),hashcode(),toString()和copy()函数

创建对象

Java:

User user = new User(1,"xuyh","adsdc234efUsd90");

Kotlin:

var user = User(1,"xuyh","adsdc234efUsd90")

Kotlin对象创建不用加new关键字,而且语句后面不用加分号”;”(即使加上也会被忽略)。

避免NullPointerException

我相信所有的开发者都曾遇到一个问题-空指针异常.

对于Java代码,编译器不会强制每次使用引用变量之前进行null判断,即异常往往会在运行时报出,而这正是危险所在。

1 var str1: String = null  //Null can not be a value of a non-null type String
2 var str2: String? = null  //str2 can be null
3 var str3 = "testNull"  //non-null--String type
4 var str4 = null  //null
5 var str5: String  //non-null--String type
6 str5 = "testNull"  //assigned String value
7 var str6  //no type or initialization
8 var str7: String? = "testNull"

结合代码中的注释,我们来看这四行代码想表达的意思。

第1行,编译错误,kotlin规定如果显式指明了str1的类型,这里是String,声明时必须同时指定是否允许为空值(null),不加问号”?”表示不允许为null;

第2行,编译通过,作第一行代码的另一种情况,加了问号,并赋值为null;

第3行,编译通过,隐式赋值为”testNull”,Kotlin会自动推断出str3类型为String,之后便不可再更改了,即不可再赋值为1这种整形数据;

第4行,编译通过,隐式赋值为null,那么str4就一直为null了;

第5-6行,编译通过,前者只是指定类型,没有赋值;后者赋予str5 String类型值”testNull”同样不能赋值为其他类型值;

第7行,编译错误,既没有指定类型,也没有隐式地进行初始化,错误的原因应该是编译器不知道str6类型是什么,不能对其分配空间;

第8行,不需多解释,str7可为null,同时赋值为”testNull”;

注意:此文为了格式统一,没有将编译或运行出错的代码注释

解释完变量定义时关于空的概念,接下来就该看看这种保护机制能否真的让我们省心。就拿获取字串的长度为例,Kotlin中String类有个length属性,即调用方式为strObject.length。

talk is cheap show me the code

1  var str2: String? = null
2  println("str2.length: " + str2.length)  //compile error
3  println("str2?.length: " + str2?.length)  //print null
4  println("str2!!.length: " + str2!!.length)  //run exception
5  if (str2 != null) {
6    println("str2!!.length: " + str2!!.length)  //don't run
7  } 
8  str2 = "testNull"  //assign
9  println("str2.length: " + str2.length)  //print 8
10 println("str2?.length: " + str2?.length)  //print 8
11 println("str2!!.length: " + str2!!.length)  //print 8
12 if (str2 != null) {
13    println("str2!!.length: " + str2.length)  //print 8
14 }

第2行,编译错误,因为之前只是将str2声明为可以是null同时赋值为null,所以紧接着访问其length属性是不允许的;

第3行,输出”null”,加了问号就会先检查str2的赋值情况,如果是null,就不继续执行后半部分(.length),直接返回null;

第4行,运行异常,不检查的后果就是通过null引用去访问length属性;

第5-7行,不会执行到if代码块中,这里用了类似Java中的做法;

第9行,输出”8”,到这里,相比能体会到Kotlin的智能之处了,在第八行对str2赋值之后,就不会再像第二行那样报编译错误了;

第10-14行,不需多解释,不为null的str2,通过三种方式均可访问length属性;

那么这里有一个疑问,用”!!”来访问属性是不明智的选择,好像”?”更稳妥一些?毕竟后者在变量是否null的情况下都能做出相应的处理。我所能想到的需要用”!!”的场景之一是:当一个变量在声明时不能马上初始化,而在真正用到时又必须是非null的。这种情况应该并不少见吧,那次此时”!!”就派上用场了。

先举一个简单粗暴的列子:

var str: String? = null
//do something to assign str
val str2: String = str!!

当声明str的时候还需后面的处理结果给它赋值,而声明str2为非null,就必须以str!!的形式才能通过编译。

类方法扩展

这个特性支持在现有类的基础上扩展方法,特别是系统库中的类,因为如果是我们自定义的类,那么扩展和添加方法没有什么差别。

方法定义

fun getArtict(): User? {
	return null
}

Kotlin中是以fun关键字声明方法,没有返回值时不需要在方法名后面写任何类型,默认是Unit类型(可写可不写,但其和null不是一回事,所以不写返回值类型或者写了Unit后不能够返回null)。

扩展

fun String.printStr() {
	println("printStr: " + this)
}

var str = "testExtend"
str.printStr()

上面代码为类String扩展了一个printStr(),这在Java中是不可能的。因为Java中如果既不能改变原有类,又想在其基础上添加方法,就得通过新建类来继承的方式。而现实是Java中只能是单继承,这个机会太珍贵了,更残酷的是有些类还是不能继承的。

总结

以上主要介绍了Kotlin,通过POJO,变量空安全,类方法扩展和java做了一个简单的比较. 我们可以看出,Kotlin还是有很大的优点的,虽然本质上只是些代码糖,但是,能够提高效率的代码糖,何乐而不为呢.


对于本文内容有问题或建议的小伙伴,欢迎在文章底部留言交流讨论。