为项目添加 Kotlin 言语的支撑
假如是现有的项目要支撑 Kotlin,只需求像下面这样操作,把两个build.gradle
中标注的代码对应贴到项目里就能够了。
-
项目根目录下的
build.gradle
: -
app 目录下的
build.gradle
:
Kotlin界说变量
- var: variable的缩写,声明变量的润饰符
var view: View
- val: value的缩写,声明只读变量的润饰符,只能复制一次,不能修正
val a: Int=10
Kotlin类型揣度
假如声明时直接赋值,则能够不写变量类型。例如:val a=10
留意:类型揣度与动态类型不同,如下所示。
- 动态类型:变量类型在运转时可改动。
- 类型揣度:代码中不用写变量类型,编译器会帮忙补上。
因此,Kotlin 是一门静态言语。
Kotlin 空安全规划
空安全规划的意图:为了避免调用空目标,呈现NullPointerException错误 Kotlin中一切变量不允许为空
lateinit
作用:让IDE不要对这个变量进行查看和报错 适用场景:我很确定这个变量到运用的时分不为空,可是在声明的时分暂时还不能给它赋值
lateinit var view: View
可空类型:类型后加?
作用:免除变量的非空约束
var name:String? = null
留意:”?”包含了非空查看.
Java中运用或许为空的变量时,我们一般会经过写if(name==null)来查看变量是否为空。可是if(name==null)查看不一定能保证name不为空,由于在多线程的状况下,别的线程或许会在查看非空后,将name的值变为null。
Kotlin中运用或许为空的变量的做法:(线程安全)
class User{
var name:String? = null
}
...
println(name?.length) //会对变量做一次非空承认后再调用办法
println(name!!.length) //也能够用双感叹号,写法不同而已
总结:报错状况
- 变量需求手动初始化,所以不初始化会报错
- 变量默许非空,所以初始化时赋值为null也报错
- 用?设置的可空变量运用时报错
留意:讨论可空/不行空,都是针对变量在运用时的状况
Kotlin的函数声明
- 以 fun 关键字最初
- 返回值写在了函数和参数后面
fun cook(name: String): Food {
...
}
假如没有返回值:
fun main(): Unit {}
// Unit 返回类型能够省掉
fun main() {}
留意:函数参数有可空控制,传参时留意可空/不行空的匹配
// 可空变量传给不行空参数,报错
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)
Kotlin中的特点的 getter/setter 函数
实例:在如下比如中,调用 hello.name
办法 , 实际上调用的是 hello.setName
办法
class Hello {
var name = "Tom"
var age = 18
}
fun main() {
var hello = Hello()
hello.name = "Jack"
}
暗地字段
在Kotlin中特点作为一级言语特性,通常状况下集暗地字段(field储值变量)+ 拜访器(getter读拜访器、setter写拜访器)于一身,无论是声明【var age: Int】、赋值【user.age = 18】、取值【println(user.age)】,从字面上看都是 age 这个特点自身,是一个全体。而只要在我们需求自界说拜访器的时分才会区别这三者。
例如自界说 setter 的时分,假如不写成暗地字段field = value,不管是 age = value 还是 this.age = value 都会报错,由于特点 age 的赋值就是setter,明显不能递归调用。
假如特点的拜访器至少有一个运用默许完成,或许自界说的拜访器中运用了 field ,那么就会提供暗地字段,用 field 关键字表示,首要用于自界说 getter/setter 时运用,也只能在 getter/setter 中拜访。
实例:
class Demo{
var id: Long = 0
get() = field
set(value) { field = value }
}
个人理解:field是一个中转变量
Kotlin中的基本类型
在 Kotlin 中,一切东西都是目标,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 等,intArrayOf 是 Kotlin 的 built-in 函数
var str: String = "string"
什么是装箱?
简略来说,原先在 Java 里的基本类型,类比到 Kotlin 里面,条件满意如下之一就不装箱:
- 不行空类型。
- 运用 IntArray、FloatArray 等。
Kotlin中的类与目标
Kotlin写法和Java写法的不同
//Kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
}
}
//Java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
}
}
写法比照
比照点 | Java | Kotlin |
---|---|---|
可见性 | 需求写明 | 默许为public,能够省掉 |
类的承继的写法 | 用extends | 用:
|
结构办法的写法 |
public MainActivity() { } (可省掉) |
单独用了一个constructor 关键字来和其他的fun 做区别:class MainActivity constructor() : AppCompatActivity() { }
|
override |
@Override 是注解的方式 |
override 变成了关键字,省掉了protected 关键字,也就是说,Kotlin 里的override 函数的可见性是承继自父类的 |
类的承继的写法 | MainActivity 可承继,由于Java 里只要加了final 关键字的类才是 final 的。 |
MainActivity 无法承继(无法作为父类),由于Kotlin 里的类默许是 final 的 |
实例化一个类 | Activity activity = new NewActivity(); |
var activity: Activity = NewActivity() |
Kotlin的open
关键字
Kotlin的类默许不行承继,所以要想让Kotlin里的MainActivity能够承继:运用open
关键字
open class MainActivity : AppCompatActivity() {}
可是要留意,此时 NewActivity 仍然是 final 的,也就是说,open
没有父类到子类的遗传性。
override
是有遗传性的,假如要封闭override
的遗传性,只需求这样即可:
open class MainActivity : AppCompatActivity() {
// 加了 final 关键字,作用和 Java 里面相同,封闭了 override 的遗传性
final override fun onCreate(savedInstanceState: Bundle?) {
...
}
}
Kotlin的abstract
关键字
Kotlin中abstract
关键字润饰的类无法直接实例化,而且通常来说会和abstract
润饰的函数一起呈现:
abstract class MainActivity : AppCompatActivity() {
abstract fun test()
}
可是子类假如要实例化,还是需求完成这个 abstract 函数的:
class NewActivity : MainActivity() {
override fun test() {}
}
Kotlin中的类型的判断和强转
Kotlin中运用is
关键字进行「类型判断」,而且由于编译器能够进行类型揣度,能够协助我们省掉强转的写法:
//Kotlin中的写法
fun main() {
var activity: Activity = NewActivity()
if (activity is NewActivity) {
// 的强转由于类型揣度被省掉了
activity.action()
}
}
//相当于Java中这么写
void main() {
Activity activity = new NewActivity();
if (activity instanceof NewActivity) {
((NewActivity) activity).action();
}
}
Kotlin中类的强转调用:运用as
关键字
fun main() {
var activity: Activity = NewActivity()
(activity as NewActivity).action()
}
更安全的强转写法:运用as?
,能够更高雅地处理强转犯错的状况。
fun main() {
var activity: Activity = NewActivity()
// '(activity as? NewActivity)' 之后是一个可空类型的目标,所以,需求运用 '?.' 来调用
(activity as? NewActivity)?.action()
}