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" }
}