Kotlin入门与进阶

本文详细介绍了Kotlin的基础语法,包括数据类型、循环、when表达式和范围操作。深入探讨了面向对象特性,如抽象类、接口、可见性、单例模式、伴生对象以及方法重载。此外,还讲解了高阶函数的概念,以及如何与Java进行混合开发。Kotlin在Android开发中的应用广泛,其简洁的语法和安全性使其成为首选语言。

Google

前言

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。苹果公司已经在用Swift语言替代Object-C语言,Google也找到了替代Java的语言,也就是JetBrains公司(Android Studio也是用该公司的Intelli J改的)主推的Kotlin。现在将kotlin作为了编写Android的官方语言

Kotlin在编写代码时有如下优势:

  1. 代码简洁高效
  2. Android Jetpack 与其他库中的 Kotlin 支持
  3. 可与 Java 的一起使用
  4. 空指针安全 *

基本语法

数据类型

不区分装箱非装箱类型,系统自动处理
Boolean、Number(Byte、Short、Int、Long、Float、Double)、Char

类型转换

  • xx.toX() 如“5”.toInt()
  • as 对象类型的转换 as? 转换失败,则为null

循环

  • for循环
    in until(不含最后一个) …(含最后一个)
    val array = arrayOf("3", "t", "d", 5)
    for (any in array) {
    }
    for (i in 0..array.size-1) {
    }
    for (i in 0 until array.size) {
    }
    for (i in array.indices) {
    }
    
  • while循环
    同java

when表达式

类似于switch,可以有返回值,可以是表达式判断

fun describe(obj: Any): String = when (obj) {
    1          -> "A"
    "a"        -> "B"
    is Long    -> "C"
    !is String -> "D"
    is String  -> "E"
    is Int     -> "F"   //不会执行,要么是D,要么是E
    else       -> "Unknown"
}

ranges

使用 in (!in) 操作符检查数值是否在某个范围内
在范围内迭代:

for (x in arrayOf(1,2,3,4,5)) {
    print(x)    //1,2,3,4,5
}
for (x in 1..10 step 2) {   
    print(x)    //1,3,5,7,9
}
for (x in 9 downTo 0 step 3) {
    print(x)    //9,6,3,0
}

数组,集合,map

数组

  • arrayOf()intArrayOf
  • arrayOfNulls<Int>(5) 指定长度为5的数组
  • set get
    • array[index]
  • 可变数组参数 String... ss == vararg ss:String

集合

  • 不可变集合
    listOf() setOf()
  • 可变集合
    mutableListOf() mutableSetOf()

使用in .contains() 检查集合中是否包含某个对象 ,in 判断的可用于when等场景

  • 常用方法:
    • 排序:
      sorted //元素升序排序
      sortedBy //对元素处理之后,再升序排序
      sortedDescending //元素降序排序
      sortedByDescending //对元素处理之后,再降序排序
      sortedWith(object: Comparator{}) //重写compare方法,自定义规则排序
    • 过滤
      filter filterNot(filter取反)
      filterIndexed { index, element -> index > element } //过滤index,或者element
      filterNotNull //舍弃为null的元素
      list1.filterIsInstanceTo(list2) //将list1中属于list2的类型的元素添加进list2

list转化为map groupBy

map

遍历

for ((k, v) in map) {
    print("$k -> $v")
}

习惯用语

  1. 数据类
    data class Customer(val name: String, val email: String)
    不可被继承,自动实现get,set(var变量),equal,hashCode,toString等方法

  2. 函数默认值
    fun foo(a: Int = 0, b: String = "bbb",c: Int) {...}
    使用:foo(a = 2, c = 7L),则b取定义的默认值

  3. 扩展函数
    fun Class.fun(){}
    如:

fun TextView?.setStyle(text: Int?) {
    this?.text = (text ?: return).toString()
    this?.textSize = 18f
}

调用方法tv.setStyle(5)
4. 创建单例模式

object Resource {
    val name = "Name"
    const val age = 18
}
  1. 只有一个表达式的函数
    fun getAge() = 42 <==> fun getAge(): Int { return 42 }

  2. with
    调用一个对象实例的多个方法

fun TextView?.setStyle(text: Int?) {
    with(this ?: return) {
        this.text = (text ?: return).toString()
        textSize = 18f
    }
}
  1. use
    Closeable对象调用,自动实现了close方法,在use方法体中写closeable的方法
val stream : InputStream! = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader()
    .use { reader: InputStreamReader ->
        println(reader.readText())
    }
  1. in
  • 判断某元素是否属于集合、数组等
  • 判断某字符是否在字符串中
  1. 字符串模板
    如:tv.setText("${a.toString()}”)
  • 字符串"""的应用
    会保留格式,转义\无效
    val s : String = """
    q
    \n
    啊
    """.trimMargin()    //移除空格
    
  1. break 和 continue 标签
aaa@ for (i in 1..10) {
    bbb@ for (j in 2..5) {
        if (j == 4) {
            break@aaa
        }
    }
}
  1. is
    等价于 instanceof !is

  • Any是所有类的父类,Nothing是所有类的子类
  • 所有的类默认是final,如果需要被继承,需要有open关键字
  • 继承,实现均由于":"替代,继承的类
  • 构造函数
    在 Kotlin 中类可以有一个主构造函数以及多个二级构造函数。主构造函数是类头的 一部分:跟在类名后面(可以有可选的类型参数)。
class Person constructor(name: String) { } 

如果主构造函数没有注解或可见性说明,则 constructor 关键字是可以省略:

class Person(name: String){ }
class A @SuppressLint("SetTextI18n") private constructor(context :Context)

初始化:

init {
}
  • 只有open修饰的方法才能被重写,且一定有override关键字

变量的定义

  1. var(可读写) val(只读) (val等价于final)
  2. lateinit var 延迟初始化(因为在定义变量的时候必须有初始值)
  3. ? 表示可为空
  4. 变量的使用
    • !! 表示非空,为空则空指针异常
    • ? 表示可为空,如果为空则不执行 或者可用
    • ?: 表示如果为空则取指定的冒号后的值

其他

  • ” 等价于 “equal”;“=” 等价于 “==”

  • set get统一 =
    如:tv.setText("a") => tv.text = "a"

第4章 面向对象

4-1 面向对象-抽象类与接口(abstract,interface)

接口中可以定义对象,可以没有初始值

4-4 类及其成员的可见性(private,protected,internal,public)

internal 模块内可见

4-5 类的鼻祖-object

  • 只有一个实例的类
  • 不能自定义构造方法
  • 可以实现接口、继承父类
  • 本质上就是单例模式最基本的实现

4-6 伴生对象与静态成员

companion object
给伴生对象的方法加上@JvmStatic或者对象@JvmField之后,就可以在java中直接使用

4-7 方法重载与默认参数

方法重载(Overlords):方法名相同,参数不同
kotlin中,list有remove(object)removeAt(index)两个方法,而在java中只有有remove(object/index)方法,如果是Integer,则只能调用remove(index)

方法中参数可以有默认值,在java中使用的话,给该方法加上@JvmOverloads即可以在java中调用用

4-8 扩展成员

扩展方法:String.aaa()
operator关键字,即为重写操作符,如加减乘除
扩展属性:
不能初始化,类似于接口里的属性

val String.a: Int
    get() = 5

4-9 属性代理

val a by lazy {
    "aaa"
}

此处即a在第一次调用的时候才会被赋值为“aaa”

定义一个class类X,val a by X()
在X类中,需要实现operator fun getValue(,property: KProperty<*>)方法
如果是var而不是val,则在X类中还需要实现operator fun setValue() 方法

4-10 数据类(allOpen,noArg插件,再见,javaBean)

知识点1

定义一个类对象的写法
val aaa = AAA(id = 1, name = "hello")
等价于
val (param1, param2) = AAA(id = 1, name = "hello")
这个param1, param2作为成员变量可以直接使用
aaa.component1()aaa.id
aaa.component2()aaa.name

备注(在Android中用不到,解决data没有无参方法和final的问题)

data class 默认是final,且没有无参构造方法(这里不符合javaBean的使用习惯,在其他地方可能有问题!)
解决(导入插件):

  1. project build.gradle
    classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
    classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
  2. 定义 annotation class X
  3. 在module build.gradle中导入该注解X
    apply plugin: 'kotlin-noarg'
    apply plugin: 'kotlin-allopen'
noArg{
    annotation("包名.X")
}
allOpen{
    annotation("包名.X")
}
  1. 给该data类添加注解@X
    注意:因为是编译期生成的无参构造方法,所以写代码的时候(在编译期之前),依然无法直接定义 val aaa = AAA()
    但是通过反射等可以拿到无参构造方法,所以数据库拿到该AAA之后可以当做javaBean使用

4-11 内部类(this@Outter,this@Inner)

  • 静态内部类
  • 非静态内部类(inner修饰)
    获取对象的方式是Outer().Inner()
    获取外部类的成员this@Outer.a
  • 匿名内部类
object: IListener1, IListener2{ }

这里其实可以多继承或实现

4-12 枚举(enum)

enum class AAA()
可以添加方法,但是必须用“;”将枚举数据与方法分开
耗性能

4-13 密封类(sealed Class)

子类有限的类
子类必须与密封类在同一个文件中
子类作为该密封类的具体体现,与枚举类类比,枚举类是实例,密封类是类对象
如:

sealed class playerCommand{
    class Play(val position: Long): playerCommand()
    object Resume(): playerCommand()
}

第5章 高阶函数

5-1 *高阶函数的基本概念

  • 传入或者返回函数的函数
  • 函数引用 ::h
  • 带有receiver的引用 a::h
class A {
    fun f() {
    }
}

访问到某方法的实例A::f
调用方式:

  1. 方法引用 ::println
  2. 类名引用 String::isEmpty
  3. 类对象引用 a::println

8-1 与Java混合开发

  1. 自动识别getter/setter
  2. 常见注解使用
    - @JvmField:将属性编译为Java变量
    - @JvmStatic:将对虾干的方法编译成Java静态方法
    - @JvmOverloads:默认参数生成重载方法
    - @file:JvmName:指定Kotlin文件编译后的类名
  3. 泛型
javakotlin
?*
ListList<*>
  1. SAM(Single Abstract Method)
    只有一个方法的接口,可以使用lamda表达式直接大括号
    条件:Java的接口,只有一个接口方法
    注意:使用的时候,大扩招中是新建一个对象,所以操作的不是同一个对象
  2. IO操作
    同java,可使用 use,调用完成自动关闭流
  3. 注解处理器
  • apply plugin:“kotlin-kapt”
  • 添加生成的代码到sourceSets(module build.gradle)
sourceSets {
	main.kotlin.srcDirs +="build/generated/souce/kapt/main"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值