总结一下基础的写法,方便自己快速的回顾。
一、 变量
在 Kotlin 中所有的变量都是不允许为 null 的。
空安全设计
但是实际场景是需要一些变量在声明的时候初始值是 null。可以如下声明:
class User{
var name : String? = null
}
Kotlin中专业术语:可空类型 。
可空类型变量调用之后会导致空指针异常,编译器会不通过编译。两种避免这种情况的写法:
//第一种写法, 编译器会做一次非空确认, safe call
var view? = null
view?.setBackgroundColor(Color.RED)
//第二种写法,坚定变量绝对不为空,实际效果就和 Java 的一样
view !!.setBackgroundColor()
延迟初始化
顾名思义,直接看如何写:
lateinit var view: View
override fun onCreate(...) {
view = findViewById(...)
}
类型推断
做为静态语言的Kotlin,可以在写变量的时候不用写变量类型。
var name = "qhh"
val 和 var
var :可读写变量
val :只读变量,只能赋值一次。
二、函数
函数声明
fun getAddress(name : String): String{
}
无返回值的写法:
fun setAddr(): Unit {}
//或者省略 Unit
fun setAddr(): {}
函数参数的注意点。参考抛物线的总结
// 可空变量传给不可空参数,报错
var myName : String? = "rengwuxian"
fun cook(name: String) : Food {}
cook(myName)
// 可空变量传给可空参数,正常运行
var myName : String? = "rengwuxian"
fun cook(name: String?) : Food {}
cook(myName)
// 不可空变量传给不可空参数,正常运行
var myName : String = "rengwuxian"
fun cook(name: String) : Food {}
cook(myName)
getter / setter 函数
var name = "qhh"
get(){
return field + " 666"
}
set(value){
field = " we " + value
}
val name = "qhh"
get(){
return field + " 666"
}
field 相当于每个 var 中的内部变量
三、 类型
基本类型
Kotlin中基本类型和Java的相差不多。但是也是有区别的地方。
1、Int类型装箱
Kotlin装箱时根据场景来决定。
var a: Int = 1 // unbox
var b: Int? = 2 // box
var list: List = listOf(1, 2) // box
装箱的过程是耗费性能的,所以尽可能的使用不可空变量。
2、数组的写法区别
Kotlin中数组的写法:(不装箱)
var array: IntArray = intArrayOf(1, 2)
使用不可空变量和IntArray等数组类型,都是不装箱的
四、类和对象
类的构造函数
1、主构造函数
主构造函数的书写方式一:
class Student constructor(name: String)
constructor 可以省略,但是在有可见性修饰符修饰以及注解则不可以省略。
主构造函数中的参数,可以在 init 函数块中进行相关业务逻辑。
class Student constructor( name: String){
val TAG = "Student"
init {
Log.d(TAG,"name is $name")
}
}
2、次构造函数
class Person {
var firstName: String
constructor(name: String){
firstName = name
}
}
3、构造函数的委托机制
通过 this 实现,有点类似 Java 中的 super
class Student constructor( name: String){
var studentName = name
var studentAge: Int = 0
init {
Log.d("qhh","name is $name")
}
constructor(age: Int,name: String) : this(name) {
studentAge = age
}
}
初始化代码块,是主构造函数的一部分,都会在次构造函数之前执行,不管有没有主构造函数都是如此。
类的继承以及接口的实现方式
interface Impl {}
class MainActivity : AppCompatActivity(), Impl {}
Kotlin中类默认都是 final 的,不可继承的。只有添加了 open 的类,子类才可以继承它。
open class Parent {
lateinit var mName: String
open fun setName(name: String): Unit {
println("setName = $name")
mName = name
}
fun work(): Unit {
}
}
子类中覆盖父类的方法必须使用 override 。
class Children : Parent() {
override fun setName(name: String) {
super.setName(name)
println("children name is $name")
}
}
抽象 abstract 关键字,在Kotlin中同样的保留。
abstract class Base {
abstract fun base() : Unit
}
同样,在 abstract 类中也可以没有 abstract 函数。
最终创建类的实例
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val student = Student("小明")
val person = Person("老刘")
val parent = Parent()
parent.setName("大明")
parent.work()
val children = Children()
children.setName("小黄")
val derive = Derive()
derive.base()
}
}
类型转化
同Java一样,子类在实例的时候是可以赋值给父类变量,反过来则不行。
var parentNew: Parent = Children()
多态的特性同样保存,并且转为父类之后,同样是无法调用子类中的方法。这个就涉及到类型的强转。Kotlin中使用到的是 is 和 as 两个操作符。
if(parentNew is Children){
parentNew.childWork("work 1")
}
(parentNew as Children).childWork("work 1")
as 配合 ?同时使用,可以处理判断类型转换的安全问题。
//表示 parentNew 是Children 类的父类或者是Children类,则执行childWork,如果不是则不执行
(parentNew as? Children)?.childWork("11")
注意: parentNew as? Children 之后是一个可空类型的对象
总结
在学习了之后大致的一个基础使用的总结。学习过程中在看的是 Kotlin的官网教程,以及 抛物线的网站。
参考:
https://www.kotlincn.net/
https://kaixue.io/kotlin-basic-1/?utm_source=androidweekly.io&utm_medium=website