Kotlin
kotlin是一门静态语言,变量类型在运行时不会改变
文章目录
一、变量
-
变量声明必须初始化,或声明成抽象的,因为变量没有默认值
-
所谓「可空不可空」,关注的全都是使用的时候,即「这个变量在使用时是否可能为空」
1.1 可空类型
对于一些可能为空的变量,如网络获取的数据,我们允许它为空值
- 声明时,在类型右边加一个?号,解除它的非空限制
- 使用时,?. 对变量做一次非空确认后再调用方法,可以做到线程安全
1.2 非空断言
- 使用时,!!.,告诉编译器不用帮我们检查了,也就和Java差不多
1.3 延迟初始化
- lateinit var view: View
1.4 可见性
- 变量默认为public
二、函数
fun cook(name: String): Food {
...
}
-
若返回值为空,可以写为
-
fun main(): Unit {}
-
fun main() {}
-
2.1 空安全设计
- 可空变量可以传给可空参数
- 不可空变量可以传给不可空参数
- 可空变量不可传给不可空参数
2.2 可见性
- 默认为public
- override时
2.3 get,set
class User {
var name = "Mike"
fun run() {
name = "Mary"
// 👆的写法实际上是👇这么调用的
// setName("Mary")
println(name)
// 👆的写法实际上是👇这么调用的
// print(getName())
}
}
如何操作
class User {
var name = "Mike"
get() {
return field + " nb"
}
set(value) {
field = "Cute " + value
}
}
- getter,setter有了专门的关键字,get,set
- getter / setter 函数位于 var 所声明的变量下面
- setter 函数参数是 value
- field对编码的人不可见,但会自动应用于 getter 和 setter
- val修饰的变量不能调用 setter 函数,因此,val 声明的变量是不能重写 setter 函数的,但它可以重写 getter 函数,取值的时候仍然可能被修改,这也是和 Java 里的 final 的不同之处。
三、类型
3.1 基本类型
- Byte,Short,Int,Long,Float,Double
- Char
- Boolean
- IntArray,CharArray等
- String
3.2 装箱
是否装箱根据场合来定,因此因尽量使用不可空类型
var a: Int = 1//unbox
var b: Int? = 2//box
var list:List<Int> = listOf(1,2)//box
四、类和对象
对于默认的MainActivity类,我们看看它在Java和kotlin中有什么不同
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
}
}
-
kotlin中可以省略修饰类的public,因为默认类是public的
-
kotlin中继承用:表示,它也同样可以表示implement
-
构造方法
-
上述kotlin写法是一种省略的写法,等价于:
class MainActivity constructor() : AppCompatActivity() { 👆 }
也等价于
// 👇注意这里 AppCompatActivity 后面没有 '()' class MainActivity : AppCompatActivity { constructor() { } }
-
-
Kotlin 省略了
protected
关键字,也就是说,Kotlin 里的override
函数的可见性是继承自父类的。- override是有遗传性的
- 可以加上final关键字关闭遗传性
-
kotlin中的类默认是final的,即不可继承,若想继承这个类,则需
open class MainActivity : AppCompatActivity() {}
- 注意,子类继承这个open后的类后,依然是final不可继承的
- 也就是说,open没有父类到子类的遗传性
五、类型强转(多态中的应用)
当我们定义了一个子类中独有的函数,父类想要调用此函数,就需要将父类转成子类调用
5.1 通过is关键字进行类型判断
fun main() {
var activity: Activity = NewActivity()
if (activity is NewActivity) {
// 👇的强转由于类型推断被省略了
activity.action()
}
}
5.2 通过as关键字直接进行强转
fun main() {
var activity: Activity = NewActivity()
(activity as NewActivity).action()
}
- 不用进行类型判断,直接进行强转调用
- 若强转成一个错误的类型,程序就会抛出异常
5.3 更好的解决方案-as?
fun main() {
var activity: Activity = NewActivity()
// 👇'(activity as? NewActivity)' 之后是一个可空类型的对象,所以,需要使用 '?.' 来调用
(activity as? NewActivity)?.action()
}
- 如果强转成功就执行之后的调用,如果强转不成功就不执行