最强总结 | 带你快速搞定kotlin开发(上篇)

源码共读

共 7912字,需浏览 16分钟

 ·

2021-08-09 18:08

👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇


作者丨Bob

来源丨IT烂笔头


Kotlin必知必会(上)


1.1 函数:


fun sum(a: Int, b: Int): Int 
    return a + b
}  
// 对于只有一行的函数,kotlin可以这么简写,爽不?
fun sum(a:Int, b:Int): Int = a + b

可以看到函数的声明是通过fun关键字的,函数的参数类型和参数名的位置跟Java是相反的,中间使用 分隔,函数的返回类型是放在最后的,当然也是使用 进行分割的,如果没有返回值的时候可以省略或者使用Unit,相当于Java的void

1.2 变量:


var age:Int = 18
val name:String = "Kotlin"
val person = Person()

使用var来声明可读可写变量,使用val来声明只读变量(引用不可变)。 
val可以理解为Java中的属性声明加上了final关键字(将kotlin的字节码反编译成Java一看就知道了),其实kotlin是更倾向于推荐使用val来声明变量,这是一种防御性的编码思维模式,目的是减少程序出错或者变的更加安全。 
可以看到实例化Person对象时,并没有声明变量类型,这就是Kotlin的“类型推断”,会自动推断出是Person类型的变量,而且是不需要Java中的new关键字的。

1.3 继承和实现接口  


class MyActivityActivity(), View.OnClickListener {
// 省略
}

一看就懂,不用多说吧。注意加上(),如果你的kotlin类能够被继承,需要使用open关键字,因为默认是final的:

open class Person {
    constructor(age: Int)
    var age: Int = 0
}
// 当你的构造函数调用父类的构造函数时,要去掉Person后面的()
class ManPerson {
    // 使用super调用父类的构造器
    constructor(age: Int): super(age)
}


1.4 空安全设计  


// 不可空类型
val person: Person

// 可空类型
val person2: Person?

那么对于可空类型的变量在调用时可以选择使用:

val person: Person? = null
// 安全调用
person?.age = 18
// 强行调用
person!!.name = "kotlin"

使用调用符,就算person是null的也不会出现空指针了,相当于Java中的判空了。当然如果你能确认person不会为空,可以使用!!强行调用符

1.5 lateinit关键字  


lateinit var person: Person
person = Person()

我们总有场景在声明的时候不知道赋什么值,在后面才去赋值的场景,那么就可以使用lateinit关键字。但是只能在以下场景下使用:

  • var声明的变量

  • lateinit修饰的变量不可空、不能是基本数据类型、不能有初始值

  • 构造器中初始化的变量不需要使用lateinit关键字


1.6 类型判断 


if(p is Person) {
    p.age = 20
}
val man: Man = Person()
val per: Person = man as Person

is关键字类似于Java中的instanceof,判断是否是什么类型,判断不是什么类型可用!is,可以看到kotlin有个小优化,就是p在条件成立时,不需要再强转了,直接被认为是Person的类型,进而可以使用Person的API。当你真的需要强转时可以使用asas?关键字,带?的在强转失败时并不会抛异常,而是返回一个null值

1.7 获取class对象


// Person.kt
Person::class
// Man.java
Man::class.java

区别于Java,kotlin要兼容Java,所以获取Java的class和kotlin的class略有不同,kotlin的class使用::class,而在kotlin中获取Java的class可以使用::class.java  

1.8 setter和getter  


class Person {
    var age: Int? = null
}
// 等价于
class Person {
    var age: Int? = null
        get() 
{
            return field
        }
        set(value) {
            field = value
        }
}

kotlin在声明非private的属性时,会默认生成对应的公开的set和get方法,当你在Java中访问时必须:

Person p = new Person();
p.setAge(20);

不过如果你就要直接访问age属性也是可以的,使用@JvmField注解:

// kotlin
class PersonAny {
    // kotlin构造函数使用constructor关键字
    constructor()
    // 加上这个注解,编译器只会生成一个public的属性,而不生成set和get方法
    @JvmField var age: Int = 19
}
// java
public class Test {
    private void some() {
        Person p = new Person();
        p.age = 20;
    }
}


1.9 数组  


open class Person {
    constructor(age: Int)
    var age: Int = 0

    fun test() {
         // 会有装箱拆箱的操作,会影响性能
        val ages = arrayOf(141516)
        // 基本数据类型使用对应的函数,比如intArrayOf()函数避免拆装箱的过程
        val ages2 = intArrayOf(141516)
    }
}

可以使用arrayOf()来创建数组。对于基本数据类型优先使用对应的函数进行创建。

1.10 静态函数和属性  


// 方法在类的外面【包级函数】或者叫【顶层函数】
fun getSomething(): Int {
    return 0
}

class Person {}

// 在Java中使用类名+Kt后缀直接访问
PersonKt.getSomething();

// 在kotlin文件中调用更加方便,只需要导包,不需要加类名
// 但是这种方式并不有利于阅读,会和类中的函数搞混淆
getSomething()

可以看到我们可以直接在文件里面声明函数,然后通过类名+Kt的方式直接调用。这种叫包级函数  

object Person {
    fun getSomething(): Int {
           return 0
    }
}

// kotlin中调用
Person.getSomething()
// java中调用
Person.INSTANCE.getSomething();

其实使用object创建类的时候,默认会生成一个单例对象,当我们使用类名来直接调用的时候,其实是通过默认的单例对象进行调用的。本质上和我们java中的静态方法还是不同的。

class Person {
    companion object {
        fun getSomething(): Int {
            return 0
        }
    }
}

// kotlin
Person.getSomething()
// java,好麻烦,但是可以使用注解@JvmStatic来让编译器编译成静态的
Person.Companion.getSomething();
// java 使用注解后就可以在Java中直接调用了
Person.getSomething();

使用companion object(伴生对象)的方式相当于有一个内部类的单例对象,这些通过kotlin的字节码反编译成Java文件就可以看出来。看起来比直接使用static关键字麻烦多了,那kotlin为啥要去掉static这个关键字呢?那得问当初设计kotlin语言的人了,从面向对象的角度来说,这么设计的确更符合万物皆对象的理念,因为static只跟类有关,而不是和对象有关。

所以,我们可以看出来使用object貌似和创建默认对象有关系,不错,比如匿名内部类(本质上就是创建一个对象)

    var view = window.decorView
    fun test() 
{
        view.setOnClickListener (object : View.OnClickListener{
            override fun onClick(v: View?) {

            }
        })
    }
    // 当然可以简写成下面这样
    fun test() {
        view.setOnClickListener {

        }
    }    


1.11 小技巧  

可以使用 ${} 来做字符串模板:

val age = 18
val info = "我是一个${age}岁的帅哥"

支持多行字符串,使用三个引号"""

    val info = """
        hhahha
        jaa
        sdfjdkjs
        jsafjs
    "
"".trimIndent()

判断数据范围和switch的使用:

// 如果年龄在10到30(包括30)
if(age in 10..30)
// 使用when取代Java中的switch,并且是支持表达式的
    when(age) {
        18->{

        }
        19->{

        }
        in 20..30-> {
        }
    }

在 Java 中通过 「 类名.this 例如 Outer.this 」 获取目标类引用  
在 Kotlin中通过「this@类名 例如this@Outer」获取目标类引用

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

浏览 6
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报