Kotlin 笔记 1 :初探 Kotlin

初探

什么是 Kotlin

Kotlin 是一种运行在 Java 虚拟机上的静态语言,由 JetBrains 设计开发,Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript。

Kotlin 兼容 Java,但比 Java 更安全,能够静态检测常见的陷阱,譬如空指针。

各种语法糖让开发更加便利,缩减代码量(事实上这点我是没感受到,写习惯了 Java,Kotlin 语法糖就是语法毒药,真难搞,可能用习惯了才会显示出优势所在)

支持函数式编程,支持比 Java8 更好的 Lambda 表达式。

......

百度谷歌的我好烦,没啥卵用,有兴趣的自己搜吧

这是它的官方网站 → 官方网站
这是它的开源地址 → 开源地址
这是它的中文官网 → 中文官网

tips: 什么是函数式编程?

为什么要学习 Kotlin

也不扯什么“工欲善其事必先利其器”这类高大上的屁话了,只有一个原因,Google 把 Kotlin 语言列为了 Android 开发的第一语言,再不学就晚了。

Kotlin 有哪些好处坏处

这玩意儿还真不好说,毕竟好不好哪里好一人一个看法,把网上烂大街的说辞抄来抄去也没啥意义,就说我目前感受到的吧:

  • 完全不用理会 Java 代码中无处不在的空指针了
  • 代码量变少了
  • 更好的支持 lambda 表达式

也说说感受到的不方便的地方吧

  • 因为是 Java 过来的,对于 Kotlin 的语法结构经常会下意识的写错
  • 语法糖来说,简直就是语法毒药,也许后期写熟练了会好一些

其实不管好处还是坏处,都是浮云,再坏你也得学不是,谁让人家是 first language。

文章的主要来源是官方文档和《Kotlin in action》 这本书,但是多了一些我的理解。

基本语法

Kotlin 源文件不需要相匹配的目录和包,源文件可以放在任意目录下。在 Java 语言当中,我们的 .java 文件必须放在其 package 表示的目录下,否则会出错,而 Kotlin 则没有这个限制。

如果没有指定包名,那默认为 default 包。

系统会默认导入一下包到 Kotlin 文件中:

  • kotlin.*
  • kotlin.annotation.*
  • kotlin.collections.*
  • kotlin.comparisons.*
  • kotlin.io.*
  • kotlin.ranges.*
  • kotlin.sequences.*
  • kotlin.text.*

和 Java 语言不通的是,Kotlin 不单单可以导入一个类,还可以单独导入一个方法:

import com.lixyz.kotlin.monthTest

fun main() {
    monthTest("哈哈")
}

定义函数

在 Kotlin 中,使用关键字 fun 来定义一个函数,一般情况下其结构是这样的:

fun 函数名(参数名:参数类型,...):返回值类型{
    //函数体
}

//例如
fun getName(id:String):String{
    ......
}

有时候可以将表达式同时作为函数体和返回值类型:

fun sum(a: Int, b: Int) = a + b

假如函数是没有返回值的,类似于 Java 语言中的 void,在 Kotlin 的关键字是 Unit,你也可以将 Unit 这个关键字省略

    fun sing(song: String): Unit {
        println("唱了一首 $song")
    }
    
    fun sing(song: String){
        println("唱了一首 $song")
    }
    //上面两个方法是一样的

定义变量

Kotlin 中使用 varval 关键字来定义变量,二者的区别在于,var 定义的变量是可以重新赋值的,而 val 定义的变量却只能在初始化的时候赋值一次,有点儿类似于 Java 中 final 修饰的变量。

一般情况下,声明一个变量的格式为:

var 变量名:变量数据类型
val 变量名:变量数据类型

但经常会这样写:

// 立即赋值
var name:String = "张三"
// 立即赋值,自动推断数据类型
val age = 20
//如果没有立即赋值的话,那么数据类型是不能省略的,下面是错误的
var name
name = "张三"

注释

注释跟 Java 用法大致上一样,// 是单行注释,/*...*/ 是多行注释,和 Java 唯一的区别是,Kotlin 允许多行注释进行嵌套,例如:

/**
*/**
** 注释内容
**/
*/

上面这种情况在 Kotlin 中是允许的,但是在 Java 中是不允许的,会报错。

字符串模板

如果有频繁的字符串拼接操作,Java 建议使用 StringBufferStringBuilder 类,在 Kotlin 中也有类似的规范,建议使用字符串模板,模板以 $ 开始开头,后面跟一个变量名或者一个表达式,如果是表达式的话,表达式需要放在大括号里:

//跟一个变量
var age = 20
println("age = $age")
//跟一个表达式
var name = "张三"
println("$name 的长度为 ${name.length}")

空置及 null 检测

在 Java 当中我们经常这样写:

String name = "李四";
name = null;

但是在 Kotlin 中,是不能这样写的:

var name:String = "张三"
name = null

在 Kotlin 中,假如某个变量可以为 null,必须在类型后面添加 ? 标识符,该标识符表明这个变量可以为空:

//这样写就没问题了
var name: String? = "张三"
name = null

对于方法的返回值如果有可能为 null 的话,同样使用 ? 标识符:

//这样写是错的
fun jointString(firstWord: String, lastWord: String): String {
    return null
}
//这样写是对的
fun jointString(firstWord: String, lastWord: String): String? {
    return null
}

Java 中的 instanceof,Kotlin 中的 is

不知道你们,反正我学 Java 的时候,这个 instanceof 关键字记了好久,在 Kotlin 中同样有相应的方法,只不过关键字改成了 is

fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        return obj.length
    }
    return null
}
//也可以这样用
fun getStringLength(obj: Any): Int? {
    if (obj !is String){
        return null
    } 
    return obj.length
}
//甚至可以这样用
fun getStringLength(obj: Any): Int? {
    if (obj is String && obj.length > 0) {
      return obj.length
    }
    return null
}

区间

Kotlin 使用 in 运算符来检测某个数字是否在指定区间内:

val x = 10
val y = 9
if (x in 1..y+1) {
    println("fits in range")
}