Android Kotlin 第一弹

151 阅读5分钟

Kotlin对比JAVA(需要补充)

  • 特性:Kotlin结合了面向对象和函数式编程,而Java仅限于面向对象编程。
  • 扩展函数:Kotlin允许创建扩展函数,而Java不提供任何扩展函数。
  • 隐式转换:Kotlin不提供隐式转换,而Java支持隐式转换。
  • 空变量或对象:Kotlin中没有空变量或对象,而Java中有空变量或对象的概念
  • 类型推导:定义变量不再需要显示声明类型,由编译器自动推导出变量的类型 如 val a ="hello” val b = 5 val c = 10L

基础

类型推导

定义变量不再需要显示声明类型,由编译器自动推导出变量的类型,编译成java 代码可以转变为基本类型

val a ="hello" //String 
val b = 5 //Int
val c = 10L //Long
val d = 1f  //Float
val f = 1.0 //Double
val g = 'T' //Char
val h = null // Any? Any 对应Java object

Any? == Object

any? 包含null

val 和 var 的使用规则

如果说 var 代表了 varible(变量),那么 val 可看成 value(值)的缩写。

但也有人觉得这样并不直观或准确,而是把 val 解释成 varible + final,即通过 val 声明的变量具有 Java 中的 final 关键字的效果,也就是引用不可变; 因为引用不可变,val 声明的变量只能被赋值一次,且在声明时不能省略变量类型。

  • 在 Kotlin 编程中,我们推荐优先使用 val 来声明⼀个本身不可变的变量,这在大部分情况下更具有优势: 这是⼀种防御性的编码思维模式,更加安全和可靠,因为变量的值永远不会在其他地方被修改(⼀些框架采用反射技术的情况除外);在Java中进行多线程开发时,由于Java的变量默认都是可变的,状态共享使得开发工作很容易出错,不可变性则可以在很大程度上避免这⼀点。

  • 不可变的变量意味着更加容易推理,越是复杂的业务逻辑,它的优势就越大。

  • 既然有了 val, 为什么还要使用 var?

  • 因为 var 有更好的性能,占用内存更少。所以,尤其是可能在业务中需要存储大量的数据的数据结构,如集合遍历中使用 var 来计算结果等,显然采用 var 是其更加适合的实现方案

编译时常量

  • val 声明的变量只能算是不可变的变量,但并不是一个常量,要定义一个真正意义上的常量,必须使用 const,const 只能修饰基本类型,且必须初始化.

  • 这样定义了一个编译时常量,等价于 java 的 static final int

  • 要放在函数的外面,因为函数里面属于运行期

// 编译时常量
const val b = 3

字符串判等

Kotlin中的判等性主要有两种类型:

内容相等。通过操作符 == 来判断两个对象的内容是否相等。

引用相等。通过操作符 === 来判断两个对象的引用是否一样,与之 相反的判断操作符是 ! == 。如果比较的是在运行时的原始类型,比如 Int,那么 === 判断的效果也等价于 ==。

var a = "Java"
var b = "Java"
var c = "Kotlin"
var d = "Kot"
var e ="lin"
var f = d + e
a == b  // true
a === b // true
c == f  // true
c === f // false

简化空对象的处理

val userName = a?.b?.c?.d ?: 

if、in、when表达式

  • if 表达式 可以替换java 三目运算;
var a0 = ture
val a = if(a0) "ture" else "false"
  • in 范围表达式

例子 1

var a0 = 10
val a = if (a0 in 0..10) "ture" else "false"
println(a)

例子 2

for (i in 0..100) {
    println(i)
}

  • when 表达式 例子 1
var a0 = 1
val a = when(a0){
    0 -> "0"
    1 -> "1"
    2 -> "2"
    else -> ""
}

例子 2

var b = 10
val a = when (b) {
    0 -> 10
    1 -> 9
    2 -> 8
    else -> 0
}
println(a)

字符串模版

val a = 1
val b = 2
val c = 3

println("sum:${a+b+c}")

函数

顶级函数

  • 在kt文件里没有在类内部的方法:顶级函数

  • 默认 kt 文件会生成一个 文件名+KT.class

  • 顶级函数生成静态方法 static


fun main() {
    f3()
}

fun f3() {
    val ret1 = f1 { "${it * 2}" } + 10
    println(ret1)
}

fun f1(f2: (Int) -> String): Int {
    return f2(5).toInt()
}

函数参数默认值 和 具名参数

认参数值、具名参数在Compose UI 中使用最多


fun f2(): String {
    return "${f1(1)}, ${f1(a = 1)}, ${f1(b = 1)}"
}

fun f1(a: Int = 0, b: Int = 0): String {
    return "${a}+${b}"
}

Unit 无返回值类型

Unit 是一个类型, 默认可以不写

表示无返回,可以对函数结果进行比较和判断;

Funtion0

函数的类型 Funtion0 中的0表示无参数,1表示一个参数,

val fun3 = {
    "fun3"
}
println(fun3)//Function0<java.lang.String>

反引号作为方法名

//数字做为名字, 做安全预防

fun `0987`():String{
    return "0987"
}
//if is in关键字
fun `if`():String {
    return "if"
}

lamda 表达式

最后一行作为隐式返回、可以使用invoke调用

//声明
val fun2 : (Int)->String
//实现
fun2 = {
    1
    1
    3
    "fun2 ${it}"
}
//调用
println(fun2(2))
println(fun2.invoke(2))

参数个数大于1个就需要具名 it 只针对一个参数时

//声明+实现 
val fun2 : (Int, Int) -> String = { i1, i2 ->
    3
    "fun2 ${i1 + i2}"
}
println(fun2(2, 4))

lamda 表达式返回值自动推导

commond+shift+p 选中可以显示类型

//声明环节省略,直接进入实现阶段,进行类型推导
val fun3 = {i1:Int->
    "fun3 ${i1}"
}
println(fun3(1))//Function0<java.lang.int,java.lang.String>

inline 内联修饰带有 lamda 表达式的函数

  • 提高性能,不使用内联,会生成多个对象,会造成性能的损耗;

  • jvm 规范会生成接口,Funtion0-9 0-9 表示参数个数;

  • 类似于 C 宏定义, 内部copy 之后不需要新建多余的对象

函数简写使用省略2、3的方式

省略 2方式

@Test
fun addition_isCorrect() {
    fun3(3, {
        println(it)
    })
}

val fun3 = { i1: Int, back: (String) -> Unit ->
    back("fun3 $i1")
}

省略 3方式


@Test
fun addition_isCorrect() {
    fun3(3) {
        println(it)
    }
}

val fun3 = { i1: Int, back: (String) -> Unit ->
    back("fun3 $i1")
}

返回函数类型对象 lamda 表达式 给另外一个对象

val fun3 = {i1:Int->
    "fun3 ${i1}"
}

函数引用 :: 获取函数类型对象

fun main() {
    //方式1
    var ret = f2(2, 3, {
        "${it} ?"
    })
    println(ret)

    //方式2
    ret = f2(2, 3, ::f1)
    println(ret)
}

fun f2(code: Int, value: Int, callBack: (Int) -> String): String {
    return "coe:$code value:$value ${callBack(code+value)}"
}

fun f1(v1: Int): String {
    return "${v1} ..."
}

普通函数返回函数类型的 lamda 表达式


fun main() {
    val ret = f1(1, "msg")(2, 2)
    println(ret)
    val a: (Int, String) -> (Int, Int) -> String = ::f1
    val b = a(1, "msg")
    //b 是一个函数类型的对象
    println(b(2, 2))
}

fun f1(code: Int, msg: String): (Int, Int) -> String {
    return { c1, c2 -> "code:$code $msg ${c1} $c2" }
}