Kotlin 学习笔记之 —— Kotlin 的变量、函数和类型

课程地址:https://kaixue.io/kotlin-basic-1/

为项目添加 Kotlin 支持

根目录下的 build.gradle

buildscript {
    // 这里配置一个全局版本号
    ext.kotlin_version = '1.3.31'
    dependencies {
        // 这里添加依赖
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

app 目录下的 build.gradle

// 使用 kotlin 的 plugin
apply plugin: 'kotlin-android'
dependencies {
    // 添加依赖
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

Kotlin 文件都是以 .kt 结尾的

变量

变量的声明与赋值

var view : View
  • 有一个 var 关键字
  • 变量名在前,类型在后,冒号分隔
  • 结尾不需要分号

Kotlin 空安全设计

非空类型

  • Kotlin 中变量是没有默认值的,需要手动初始化
  • Kotlin 默认声明变量是非空的,不能赋值为 null

可空类型

  • 声明可空变量需要在类型右边加一个问号,被称为可空类型
var name: String? = null
  • 调用可空类型变量时不能手动判断是否为空,需要使用 ?. ,被称为「safe call」
view?.setBackgroundColor(Color.RED)
  • 还有一种双叹号的写法,被成为「断言式写法」,编译器不再做检查
view!!.setBackgroundColor(Color.RED)

关于空安全,最重要的是记住一点:所谓「可空不可空」,关注的全都是使用的时候,即「这个变量在使用时是否可能为空」。

Kotlin 和 Java 的空安全设计兼容

  • Kotlin 中调用 Java 中 @Nullable 变量
name?.length
  • Java 中 @Nullable 和 @NonNull 注解可以自动转化为 Kotlin 代码
// Java
@Nullable
String name;
@NonNull
String value = "hello";
// Kotlin
var name: String? = null
var value: String = "hello"

延迟初始化

lateinit 关键字适用于声明时不能赋值,但是能保证使用之前一定会赋值的场景,例如 Activity 中的 View:

lateinit var view: View

override fun onCreate(...) {
    view = findViewById(R.id.view)
}

类型推断

可以在声明变量时不指定变量类型,自动推断。

var name = "Daniel"

动态类型指变量的类型在运行时可以改变,类型推断指在代码里不用写变量类型,编译器会自动推断,Kotlin 是静态语言,不支持动态类型。

var 和 val

val 是只读变量,只能复制一次,类似 Java 中的 final。

var 是 variable 的缩写,val 是 value 的缩写

可见性

Kotlin 中的变量默认是 public 的。

函数

函数的声明

fun cook(name: String): Food {
    ...
}
  • 以 fun 关键字开头
  • 返回值写在函数名和参数后面
  • 没有返回值对应的类型是 Unit,并且可以省略
  • 函数参数和返回值类型可以是可空类型

可见性

默认也是 public

属性的 getter/setter 函数

调用属性时其实调用的是它的 getter 和 setter。

var name = "Daniel"
    get() {
        return field + " nb!!"
    }
    set(value) {
        field = "good " + value
    }
  • getter / setter 函数有了专门的关键字 get 和 set
  • getter / setter 函数位于 var 所声明的变量下面
  • setter 函数参数是 value
  • 使用 field 表示背后的字段
  • val 变量不能重写 setter,但可以重写 getter,而且取值时还能修改
fun main() {
    // 虽然 name 是 val,但这里打印的值每次都不一样
    println(Dog().name)
}
class Dog{
    val name = "dog"
        get() {
            return field + System.currentTimeMillis()
        }
}

类型

基本类型

在 Kotlin 中,所有的东西都是对象,使用的基本类型有:数字、字符、布尔值、数组与字符串。

var number: Int = 1 // 还有 Double Float Long Short Byte 等
var c: Char = 'c'
var b: Boolean = true
var array: IntArray = intArrayOf(1, 2) // 还有 FloatArray DoubleArray CharArray 等
var str: String = "string"

和 Java 中的区别:

  • Int 是否装箱根据场合来定
var a:Int = 1 // unbox
var b: Int? = 2 // box
var list: List<Int> = listOf(1, 2) // box
  • 数组的写法是有区别的
var array: IntArray = intArrayOf(1, 2) // unbox
  • 不可空类型、使用 IntArray、FLoatArray 等不会装箱
  • 个人理解,是否装箱取决于背后使用的是不是对象引用以及会不会为空

类和对象

  • Kotlin 中的类默认是 public 的,可以省略

  • 类的继承使用 : 代替 extends 或者 implement

  • 构造方法写法不同

    • Java 中会省略默认构造函数
    • Kotlin 下面这几种写法都可以
    // 省略构造函数的写法
    class MainActivity : AppCompatActivity() {}
    // 等价的写法
    class MainActivity constructor() : AppCompatActivity() {}
    // 更像 Java 的写法
    class MainActivity : AppCompatActivity {
        constructor() {
        }
    }
    
    • Kotlin 构造函数使用 constructor 关键字
  • override 的不同

    • Java 中使用 @Override 注解
    • Kotlin 使用 override 关键字
    • Kotlin 中省略了 protected 关键字,Kotlin 中的 override 函数的可见性是继承自父类的
  • Kotlin 中的类默认是 final 的,可以使用 open 关键字解除

    • 子类不继承 open 属性
    • 子方法会继承 open 属性,可以使用 final 关闭
  • Kotlin 中也可以用 abstract 关键字声明抽象类,同 Java

  • Kotlin 中创建对象不需要 new 关键字

类型的判断和强转

  • Kotlin 中使用 is 判断类型,并且可以省略强转
fun main() {
    var activity: Activity = SubActivity()
    if (activity is SubActivity) {
        // 强转由于类型推断被省略了
        activity.subFun()
    }
}
  • Kotlin 使用 as 关键字强转(同 Java ),使用 as? 来进行安全强转
// 强转
fun main() {
    var activity: Activity = SubActivity()
    (activity as SubActivity).subFun()
}
// 安全强转
fun main() {
    var activity: Activity = SubActivity()
    // 注意安全强转后是可空类型,需要使用 ?. 调用
    (activity as? SubActivity)?.subFun()
}

思考题

  1. 子类重写父类的 override 函数,能否修改它的可见性?

可以放宽,不能收窄,否则多态调用的时候将无法调用子方法,同 Java。

open class Bird {
    protected open fun fly(){
        print("bird fly...")
    }
}

class Eagle : Bird(){
    // 可以
    public override fun fly(){
        print("eagle fly...")
    }
}

class Canary : Bird(){
    // 报错
    private override fun fly(){
        print("canary fly...")
    }
}
  1. 以下的写法有什么区别?
activity as? NewActivity
activity as NewActivity?
activity as? NewActivity?

as? 表示安全强转,NewActivity? 表示转换为可空类型,两者并不矛盾,分情况讨论。

activity 值 null NewActivity 非空实例 其它类型
activity as? NewActivity 不执行 转换成功 不执行
activity as NewActivity? 转换结果为 null 转换成功 ClassCastExecption
activity as? NewActivity? 转换结果为 null 转换成功 不执行
  • 第一种写法只有当 activity 为 NewActivity 非空实例时会做强转,否则不执行;
  • 第二种写法是不安全强转,不管 activity 是什么类型,也不管是不是 null 都会强转,转换失败会抛出 ClassCastException;
  • 第三种写法也是安全强转,如果 activity 是 NewActivity 的实例或者 null,都会安全转换为 NewActivity? 类型,否则不执行。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容