Google在2017年的I/O大会上宣布,Kotlin正式成为 Android的一级开发语言,和Java平起平坐,Android Studio也对Kotlin进行了全面的支持。Google更加推荐开发者使用Kotlin来编写Android应用程序, 并且未来提供的官方API也将会优先考虑Kotlin版本。
打算苦学Android,并使用Kotlin,那么便有了此独门快速入门秘籍。而我使用Kotlin的唯一原因是它更简洁。
如果略懂Java,学习Kotlin就十分简单了,本秘籍快速入门Kotlin,通过与Java对比着学习以增加特殊语法的印象。
1、面向对象
学java的都知道,万物皆对象。
Kotlin同样是面向对象的。
同样,有 类,属性,方法。
属性呢,就是常量和变量,先看变量:
在Kotlin中定义变量的方式和Java区别很大,在Java中如果想要定义一个变 量,需要在变量前面声明这个变量的类型,比如说int a表示a是一个整型变量,String b表 示b是一个字符串变量。而Kotlin中定义一个变量,只允许在变量前声明两种关键字:val和 var。val(value的简写)用来声明一个不可变的变量,这种变量在初始赋值之后就再也不能重新赋 值,对应Java中的final变量。var(variable的简写)用来声明一个可变的变量,这种变量在初始赋值之后仍然可以再被重新 赋值,对应Java中的非final变量。Kotlin比较有特色的一点,它拥有出色的 类型推导机制,这点和js有些像。
如果你学过Java并且足够细心的话,你可能发现了Kotlin中Int的首字母是大写的,而Java中 int的首字母是小写的。不要小看这一个字母大小写的差距,这表示Kotlin完全抛弃了Java中的 基本数据类型,全部使用了对象数据类型。在Java中int是关键字,而在Kotlin中Int变成了一 个类,它拥有自己的方法和继承结构。
函数:
fun methodName(param1: Int, param2: Int): Int { return 0 } 下面我来解释一下上述的语法规则,首先fun(function的简写)是定义函数的关键字,无论你 定义什么函数,都一定要使用fun来声明。紧跟在fun后面的是函数名,这个就没有什么要求了,你可以根据自己的喜好起任何名字,但是 良好的编程习惯是函数名最好要有一定的意义,能表达这个函数的作用是什么。函数名后面紧跟着一对括号,里面可以声明该函数接收什么参数,参数的数量可以是任意多 个,例如上述示例就表示该函数接收两个Int类型的参数。参数的声明格式是“参数名: 参数类 型”,其中参数名也是可以随便定义的,这一点和函数名类似。如果不想接收任何参数,那么写 一对空括号就可以了。参数括号后面的那部分是可选的,用于声明该函数会返回什么类型的数据,上述示例就表示该 函数会返回一个Int类型的数据。如果你的函数不需要返回任何数据,这部分可以直接不写。最后两个大括号之间的内容就是函数体了,我们可以在这里编写一个函数的具体逻辑。由于上 述示例中声明了该函数会返一个Int类型的数据,因此在函数体中我们简单地返回了一个0。
注意,Kotlin每一行代码的结尾是不用加分号的,如果你写惯了Java的话,在这里得先熟悉一 下。
接下来我们尝试按照上述定义函数的语法规则来定义一个有意义的函数,如下所示:
fun largerNumber(num1: Int, num2: Int): Int { return max(num1, num2) }
这里定义了一个名叫largerNumber()的函数,该函数的作用很简单,接收两个整型参数,然 后总是返回两个参数中更大的那个数。
我们再来学习一个Kotlin函数的语法糖,这个语法糖在以后的开发中会起到相 当重要的作用。当一个函数中只有一行代码时,Kotlin允许我们不必编写函数体,可以直接将唯一的一行代码写 在函数定义的尾部,中间用等号连接即可。比如我们刚才编写的largerNumber()函数就只有 一行代码,于是可以将代码简化成如下形式:
fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2)
使用这种语法,return关键字也可以省略了,等号足以表达返回值的意思。另外,还记得 Kotlin出色的类型推导机制吗?在这里它也可以发挥重要的作用。由于max()函数返回的是一个 Int值,而我们在largerNumber()函数的尾部又使用等号连接了max()函数,因此Kotlin可 以推导出largerNumber()函数返回的必然也是一个Int值,这样就不用再显式地声明返回值 类型了,代码可以进一步简化成如下形式:
fun largerNumber(num1: Int, num2: Int) = max(num1, num2)
2、程序的逻辑控制
if语句:
Kotlin中的条件语句主要有两种实现方式:if和when
Kotlin中的if语句相比于Java有一个额外的功能,它是可以有返回值的,返回值就是if语句每 一个条件中最后一行代码的返回值。
if语句使用每个条件的最后一行代码作为返回值,并将返回值赋值给了 value变量。由于现在没有重新赋值的情况了,因此可以使用val关键字来声明value变量,最 终将value变量返回。
仔细观察上述代码,你会发现value其实也是一个多余的变量,我们可以直接将if语句返回, 这样代码将会变得更加精简,如下所示:
when:
is关键字就是类型匹配的核心,它相当于Java中的instanceof关键字。由于 checkNumber()函数接收一个Number类型的参数,这是Kotlin内置的一个抽象类,像Int、 Long、Float、Double等与数字相关的类都是它的子类。
循环语句:
Java中主要有两种循环语句:while循环和for循环。而Kotlin也提 供了while循环和for循环,其中while循环不管是在语法还是使用技巧上都和Java中的 while循环没有任何区别,它们的while循环用法基本是相同的。
Kotlin在for循环方面做了很大幅度的修改,Java中最常用的for-i循环在Kotlin中直接被舍弃 了,而Java中另一种for-each循环则被Kotlin进行了大幅度的加强,变成了for-in循环,所 以我们只需要学习for-in循环的用法就可以了。
在开始学习for-in循环之前,还得先向你普及一个区间的概念,因为这也是Java中没有的东 西。我们可以使用如下Kotlin代码来表示一个区间:
上述代码表示在遍历[0, 10)这个区间的时候,每次执行循环都会在区间范围内递增2,相当于 for-i循环中i = i + 2的效果。
for-in循环除了可以对区间进行遍历之外,还可以用于遍历数组和集合。
类与对象:
Kotlin中也是使用class关键字来声明一个类
继承和构造函数:
创建两个类:
现在Student和Person这两个类之间是没有任何继承关系的,想要让Student类继承Person 类,我们得做两件事才行。第一件事,使Person类可以被继承。可能很多人会觉得奇怪,尤其是有Java编程经验的人。一 个类本身不就是可以被继承的吗?为什么还要使Person类可以被继承呢?这就是Kotlin不同的 地方,在Kotlin中任何一个非抽象类默认都是不可以被继承的,相当于Java中给类声明了final 关键字。之所以这么设计,其实和val关键字的原因是差不多的,因为类和变量一样,最好都是 不可变的,而一个类允许被继承的话,它无法预知子类会如何实现,因此可能就会存在一些未 知的风险。Effective Java这本书中明确提到,如果一个类不是专门为继承而设计的,那么就应 该主动将它加上final声明,禁止它可以被继承。
在Person 类的前面加上open关键字就可以继承了。
第二件事,要让Student类继承Person类。在Java中继承的关键字是extends,而在Kotlin 中变成了一个冒号,写法如下:
到这里为止都还挺好理解的吧?但是这和那对括号又有什么关系呢?这就涉及了Java继承特性 中的一个规定,子类中的构造函数必须调用父类中的构造函数,这个规定在Kotlin中也要遵守。
那么回头看一下Student类,现在我们声明了一个主构造函数,根据继承特性的规定,子类的 构造函数必须调用父类的构造函数,可是主构造函数并没有函数体,我们怎样去调用父类的构 造函数呢?你可能会说,在init结构体中去调用不就好了。这或许是一种办法,但绝对不是一 种好办法,因为在绝大多数的场景下,我们是不需要编写init结构体的。Kotlin当然没有采用这种设计,而是用了另外一种简单但是可能不太好理解的设计方式:括号。子类的主构造函数调用父类中的哪个构造函数,在继承的时候通过括号来指定。因此再来看一 遍这段代码,你应该就能理解了吧。
任何一个类只能有一个主构造函数,但是可以有多个次构造函数。次构造函数也可 以用于实例化一个类,这一点和主构造函数没有什么不同,只不过它是有函数体的Kotlin规定,当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造 函数(包括间接调用)。这里我通过一个具体的例子就能简单阐明,代码如下:
接口:
接口是用于实现多态编程的重要组成部分。我们都知道,Java是单继承结构的语言,任何一个 类最多只能继承一个父类,但是却可以实现任意多个接口,Kotlin也是如此。
Kotlin还增加了一个额外的功能:允许对接口中定义的函数进行默认实现。其实Java在JDK 1.8之后也开始支持这个功能了,因此总体来说,Kotlin和Java在接口方面的功能仍然是一模一 样的。
接下来我们再学习一个和Java相比 变化比较大的部分——函数的可见性修饰符。熟悉Java的人一定知道,Java中有public、private、protected和default(什么都不 写)这4种函数可见性修饰符。Kotlin中也有4种,分别是public、private、protected和 internal,需要使用哪种修饰符时,直接定义在fun关键字的前面即可。下面我详细介绍一下 Java和Kotlin中这些函数可见性修饰符的异同。首先private修饰符在两种语言中的作用是一模一样的,都表示只对当前类内部可见。public 修饰符的作用虽然也是一致的,表示对所有类都可见,但是在Kotlin中public修饰符是默认 项,而在Java中default才是默认项。前面我们定义了那么多的函数,都没有加任何的修饰 符,所以它们默认都是public的。protected关键字在Java中表示对当前类、子类和同一包 路径下的类可见,在Kotlin中则表示只对当前类和子类可见。Kotlin抛弃了Java中的default可 见性(同一包路径下的类可见),引入了一种新的可见性概念,只对同一模块中的类可见,使 用的是internal修饰符。比如我们开发了一个模块给别人使用,但是有一些函数只允许在模块 内部调用,不想暴露给外部,就可以将这些函数声明成internal。
数据类与单例类:
数据类通常需要重写equals()、hashCode()、toString()这几个方法。其中,equals() 方法用于判断两个数据类是否相等。hashCode()方法作为equals()的配套方法,也需要一起 重写,否则会导致HashMap、HashSet等hash相关的系统类无法正常工作。toString()方法 用于提供更清晰的输入日志,否则一个数据类默认打印出来的就是一行内存地址。
接下来我们再来看另外一个Kotlin中特有的功能——单例类。想必你一定听说过单例模式吧,这是最常用、最基础的设计模式之一,它可以用于避免创建重 复的对象。比如我们希望某个类在全局最多只能拥有一个实例,这时就可以使用单例模式。当 然单例模式也有很多种写法,这里就演示一种最常见的Java写法吧:
基础语法秘籍到此结束。
发表评论