Kotlin——基础语法
定义函数
带有两个Int参数、返回Int的函数:
1 | fun sum(a: Int, b: Int): Int { |
表达式作为函数体、返回值类型自动推断的函数:
1 | fun sum(a: Int, b: Int) = a + b |
返回无意义的值:
1 | fun printSum(a: Int, b: Int): Unit { |
省略Unit返回类型:
1 | fun printSum(a: Int, b: Int) { |
定义变量
只读变量
只读变量用val
修饰:
1 | val a: Int = 1 //立即赋值 |
可变变量
可变变量用var
修饰:
1 | var x = 5 //自动推断出Int类型 |
Android Studio Java 和 Kotlin混合编译配置
Java和Kotlin的混编,按场景分一下两种:
- Java 调用 Kotlin(如Java编写的Activity里面按钮点击,开启一个Kotlin编写的Activity
- Kotlin 调用 Java(如Kotlin编写的Activity里面按钮点击,开启一个java编写的Activity
具体配置
下面讲一下怎么配置才能满足混合编译的配置
根项目下的build.gradle文件配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24buildscript {
ext.kotlin_version = '1.6.10'
repositories {
...
}
dependencies {
// gradle 插件版本
classpath 'com.android.tools.build:gradle:3.6.1'
// kotlin gradle 插件版本,这个版本要与Android Studio的插件版本序号一致
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// 扩展插件可以节省findviewbyid(),实现与Data-Binding,Dagger框架的效果,不需要添加任何额外代码,也不影响任何运行时体验。
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
...
}
}module项目下的build.gradle文件配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24apply plugin: 'com.android.application'
// 下面两种写法都可以
//apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-android'
android({
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
compileOptions {
sourceCompatibility javaVersion
targetCompatibility javaVersion
}
kotlinOptions {
jvmTarget = '1.8'
}
dependencies {
dependencies {
// 这个可以不用,作用Android KTX 是包含在 Android Jetpack 及其他 Android 库中的一组 Kotlin 扩展程序。KTX 扩展程序可以为 Jetpack、Android 平台及其他 API 提供简洁的惯用 Kotlin 代码。
implementation "androidx.core:core-ktx:1.6.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
}
关于android KTX,请参考Android KTX
这样就可以配置就完成了
问题
Java调用Kotlin没什么问题,主要是在Kotlin的Activity中调用Java方法(或开启Java的Activity)时,如果Java 类文件不在main/java
下,就会出现找不到引用的问题,这个目前没有搜到相应的解决办法,后面知道了会跟新记录
NULL检查机制
注意点1
都知道Kotlin有空安全机制,这样可以避免Java中crash最常见的罪魁祸首NPE出现,但还是要知道Kotlin空安全的具体使用的。具体来说,Kotlin对于声明为可为空的参数,在使用时要进行判空处理具体有以下两种方式:
- 可为空字段后面加上
!!
,表示当字段为空时,会像Java一样抛出空指针异常; - 可为空字段后面加上
?
,表示不做处理返回值为null或者配合?:
做判空处理;
具体看下面的例子:
1 | //类型后面加?表示可为空 |
注意点2
当引用一个可能为null的值时,对应的类型声明必须明确的标记为可为null
具体例子:
1 | // 当 str 中的字符串内容不是一个整数时, 返回 null,函数返回值类型必须为 Int? |
类型检测及自动类型转换
Kotlin中类型检测采用 is
关键字来表示,类似于 Java中的 instanceOf
关键字,但Kotlin中会有一个更便捷的地方,就是采用 is
检测后,就自动转换成对应的类型了,不用像Java中那样在现实的强转一下,具体看一下例子:
1 | fun getStringLength(obj : Any) : Int? { |
扩展
Kotlin可以对一个类的属性和方法进行扩展,且不许要使用继承或者Decorator模式;
扩展函数可以在已有类
object
关键字
kotlin增加了一个 object
关键字,该关键字用于以下场景中:
- 对象表达式,相当于Java中的匿名内部类;
- 对象声明,kotlin中提供的一个简洁的单例声明方式;
- 伴生对象,kotlin中替代Java 中static功能的方式;
对象表达式
对象表达式,类似于Java中的匿名内部类:
1 | interface OnClickListener { |
注意:
listener =
可以省略
关于对象表达式,还有以下要知道的:
- 对象表达式 object 冒号后面可以有多个超类,
- 对象表达式 的超类如果包含带参数的构造函数,则在声明的时候需要传递相应的参数;
- 匿名对象智能在 本地 和 私有声明 中作为类型使用,如果对象表达式采用了 public 关键字修饰,则匿名对象的实际类型是 匿名对象的超类型(没有超类型则 类型为Any),public 修饰的匿名对象 里成员将不可访问。
- 对象表达式可以访问外部类的成员,并且外部类没必要声明为final,这一点同Java不一样。
对象声明
对象声明是Kotlin (在Scala之后)实现单例的一种快捷方式,即kotlin中可以像声明变量那样采用关键字来声明单例,而不用像Java那样需要自己 去实现单例。这个关键字就是 object
,该关键字后面直接接类名时,那么这个类就只有一个对象,例如:
1 | object DialogManager : BaseDialogManager() { |
由上面的示例可见,对象声明 时 类可以有超类。对象声明虽然方便,但也有几个局限的地方:
- 对象声明 时 没有 右值的,所以不能作为表达式那样复制个其他变量,这一点Java的单例是可以的;
- 对象声明 不能 是本地的,即不能放在函数作用域中,可以在类作用域(类里面声明)使用;
- 对象声明 可以继承超类,即单例可以有超类。
伴生对象
伴生对象(companion object)的出现是为了解决 Java 静态方法(static)的反面向对象(Anti-OOP)的问题。即Java 中 static 方法是无法声明为接口、无法被重写的,也就是说 static方法没有面向对象的 消息传递 和 延迟绑定 特性。而Kotlin中一切皆对象,多以采用伴生对象来替代static方法。
companion object 是一个对象,在类初始化时被实例化。注意 伴生对象不是类的 static 方法,而是类的实例化对象,其内部可以声明接口,方法也可以被重写,具备面向对象的特点。
伴生对象声明方式
1 | companion object ObjectName : [0~N个父类型] { |
伴生对象的特点:
- 伴生对象相当于类的对象,可以直接通过类名访问伴生对象的成员;
- 每个类最多定义一个伴生对象;
- kotlin中没有 static关键字,伴生对象是为了弥补kotlin中没有 static 修饰的静态成员的不足;
- @JvmStatic 注解只能用在伴生对象内,修饰伴生对象内的属性和函数;
协程
操作符
安全调用操作符
?.
功能:安全调用操作符 ?. 用于在调用方法或访问属性时,确保如果左侧表达式为 null,则整个表达式的值为 null,而不会抛出异常。
使用场景:当你不确定某个对象是否为 null,并且希望在对象为 null 时不执行后续操作时,可以使用 ?.。
非空断言操作符
!!.
功能:非空断言操作符 !!. 用于强制将一个可空类型的值转换为非空类型。如果该值为 null,则会抛出 NullPointerException。
使用场景:当你确定某个对象不会为 null,并且希望在对象为 null 时立即抛出异常而不是继续执行代码时,可以使用 !!.。