kotlin的一点知识

1. kotlin对象声明

1
2
3
4
5
object Hello {
var age : Int = 0
fun sayHello() : Unit {
}
}

对象生命可以看做是全局的静态函数

1
2
kotlin中调用 : Hello.sayHello()
java中调用   : Hello.Instance.sayHello()

通过反编译可以看到 , 所谓对象声明是在字节码底层,声明了当前class的实例,
在static代码块中进行实例对象初始化

1
2
3
4
5
6
7
public final class Hello {
public static final Hello INSTANCE;
public final int getAge();
public final void sayHello();
static {};
}

kotlin伴生对象

1
2
3
4
5
6
7
8
9
10
11
class Hello4 {
var age : Int = 0
get() {return field}


companion object {
fun test(): Unit{

}
}
}
1
2
3
4
5
6
7
8
9
10
伴生对象字节码揭秘 

public final class Hello4 {
public static final Hello4$Companion Companion;
public Hello4();
public final int getAge();
public final void setAge(int);
static {};
}

kotlin扩展函数

1
fun Hello.sayBey() = print("bey")

扩展函数回在声明了当前扩展函数的类中添加一个新的static函数,把被扩展的class当做参数传入

1
2
字节码揭秘: 
public static final void sayBey(Hello);

kotlin 内部类和嵌套类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Outer {

var name : String = "zhangsan"

class Nested {
fun test() {
}
}

inner class Inner {
fun test() {
this@Outer.name
}
}
}

看调用

1
2
3
4
fun main() {
Outer.Nested().test()
Outer().Inner().test()
}

看字节码 ,区别在于inner修饰的class在内部会持有外部类的引用,类似于java的内部类。
而嵌套类更类似于java中static修改的内部class

1
2
3
4
5
6
7
8
9
10
11
12
public final class Outer$Inner {
final Outer this$0;
public Outer$Inner();
public final void test();
}

public final class Outer$Nested {
public Outer$Nested();
public final void test();
}


kotlin 数据类和数据对象

data修饰的object和class会在字节码底层增加field对应的set/get函数。 hashCOde,toString,equals函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
数据对象:
data object DataObj {
lateinit var name : String

}
对应字节码:
public final class DataObj {
public static final DataObj INSTANCE;
public static java.lang.String name;
public final java.lang.String getName();
public final void setName(java.lang.String);
public java.lang.String toString();
public int hashCode();
public boolean equals(java.lang.Object);
static {};
}

数据对象在字节码底部会声明当前object的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
数据类: 至少有一个构建参数
data class DataClazz(val name: String)
数据类字节码:
public final class DataClazz {
public DataClazz(java.lang.String);
public final java.lang.String getName();
public final java.lang.String component1();
public final DataClazz copy(java.lang.String);
public static DataClazz copy$default(DataClazz, java.lang.String, int, java.lang.Object);
public java.lang.String toString();
public int hashCode();
public boolean equals(java.lang.Object);
}

kotlin类委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface ImageLoader{
fun load(url: String)
}
class FresoLoader : ImageLoader {
override fun load(url: String) {
println("load $url with freso")
}
}
class ImageLoaderEngine(imageLoader: ImageLoader) : ImageLoader by imageLoader

fun main() {
val engine = ImageLoaderEngine(FresoLoader())
engine.load("http:xx.png")
}

本质上,kotlin在设计层面提供了类似于java包装类的做法,在ImageLoaderEngine底层维持了传入的FresoLoader对象,并且在对应的函数里面使用FresoLoader去进行调用分发

kotlin属性委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import kotlin.reflect.KProperty
import Test10 as Test101

class Test10 {
operator fun getValue(nothing: Nothing?, property: KProperty<*>): String {
println("getValue invoked")
return ""
}

operator fun setValue(nothing: Nothing?, property: KProperty<*>, s: String) {
println("setValue invoked")
}
}

var name : String by Test101()

var addr : String by Test101()

fun main() {
name
}

在底层字节码回根据当前被委托属性的个数去维护一个 KProperty数组

1
static final kotlin.reflect.KProperty<java.lang.Object>[] $$delegatedProperties;

用对应的委托对象,去代理到具体的实现类

kotlin 可观测委托

1
2
3
4
5
6
7
8
9
10
//在value被修改以后,提供一个回调函数去进行观测
var student : String by Delegates.observable("") {
prop ,oldValue ,newValue ->
}

//在字段的值被修改之前进行函数回调, true:修改,fanse: 不修改
var student2 : String by Delegates.vetoable("") {
prop ,oldValue ,newValue ->
true
}

kotlin 提供委托

提供委托就是一个委托类的提供者,通过provideDelegate函数进行返回需要的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class StrDelegate  {
operator fun provideDelegate(thisRef: Test, property: KProperty<*>) : ReadWriteProperty<Test , String>{
return when(property.name) {
"hello" -> Delegate1()
else -> Delegate2()
}
}

}

class Delegate2 : ReadWriteProperty<Test, String> {
override fun getValue(thisRef: Test, property: KProperty<*>): String {
TODO("Not yet implemented")
}

override fun setValue(thisRef: Test, property: KProperty<*>, value: String) {
TODO("Not yet implemented")
}
}
class Delegate1 : ReadWriteProperty<Test, String> {
override fun getValue(thisRef: Test, property: KProperty<*>): String {
TODO("Not yet implemented")
}

override fun setValue(thisRef: Test, property: KProperty<*>, value: String) {
TODO("Not yet implemented")
}
}

class Test {
var student3 : String by StrDelegate()
}