Kotlin笔记 09 - 委托
委托类12345678910111213141516171819202122232425interface DB { fun save()}class SqlDB() : DB { override fun save() { println("save to sql") }}class GreenDaoDB() : DB { override fun save() { println("save to GreenDao") }}// 参数 通过 by 将接口实现委托给 db // ↓ ↓class UniversalDB(db: DB) : DB by dbfun main() { UniversalDB(SqlDB()).save() UniversalDB(GreenDaoDB()).save()}/*输出:sa ...
Kotlin笔记(附加)
函数式编程
命令式编程,其实就是最常见的编程方式:在编程的时候,我们需要告诉计算机每一步具体都要干什么。
1234567891011fun foo(): List<Int> { val list = listOf(1, 2, 3, 4) val result = mutableListOf<Int>() for (i in list) { if (i % 2 == 0) { result.add(i) } } return result}
函数式,或者说“声明式”的代码
1fun fp() = listOf(1, 2, 3, 4).filter { it % 2 == 0 }
区别:
它只需要声明我们想要什么,而不必关心底层如何实现。
代码更加简洁,可读性更高。
3.0 版本的词频统计程序,其实并没有完全发挥出 Kotlin 函数式编程的优势,因为其中的“getWordCount()”“mapToLis ...
Kotlin笔记 08 - inline
高阶函数实现原理由于 Kotlin 兼容 Java 1.6,因此 JVM 是不懂什么是高阶函数的,我们的高阶函数最终一定会被编译器转换成 JVM 能够理解的格式。
123456789101112// HigherOrderExample.ktfun foo(block: () -> Unit) { block()}fun main() { var i = 0 foo{ i++ }}
反编译成 Java 后
1234567891011121314public final class HigherOrderExampleKt { public static final void foo(Function0 block) { block.invoke(); } public static final void main() { int i = 0 foo((Function0)(new Function0() ...
Kotlin笔记 07 - 高阶函数
函数类型123// (Int, Int) ->Float 这就是 add 函数的类型// ↑ ↑ ↑fun add(a: Int, b: Int): Float { return (a+b).toFloat() }
将函数的“参数类型”和“返回值类型”抽象出来后,就得到了“函数类型”。(Int, Int) ->Float 就代表了参数类型是两个 Int,返回值类型为 Float 的函数类型。
函数的引用123// 函数赋值给变量 函数引用// ↑ ↑val function: (Int, Int) -> Float = ::add
高阶函数高阶函数是将函数用作参数或返回值的函数。如果我们将 Android 里点击事件的监听用 Kotlin 来实现的话,它其实就是一个典型的高阶函数。
123// 函数作为参数的高阶函数// ...
Kotlin笔记 06 - 扩展
扩展函数12345678910111213141516171819202122// Ext.ktpackage com.boycoder.chapter06/* ① ② ③ ④ ↓ ↓ ↓ ↓ */fun String.lastElement(): Char? { // ⑤ // ↓ if (this.isEmpty()) { return null } return this[length - 1]}// 使用扩展函数fun main() { val msg = "Hello Wolrd" // lastElement就像String的成员方法一样可以直接调用 val last = msg.lastElement() // last = d}
在整个扩展函数的方法体当中,this 都是可以省略的。
实现原理反编译后的 Java 代码
1234 ...
Kotlin笔记 05 - object
object 关键字,有三种迥然不同的语义,分别可以定义:
匿名内部类;
单例模式;
伴生对象。
Kotlin 的设计者认为,这三种语义本质上都是在定义一个类的同时还创建了对象。在这样的情况下,与其分别定义三种不同的关键字,还不如将它们统一成 object 关键字。
object:匿名内部类12345image.setOnClickListener(object: View.OnClickListener { override fun onClick(v: View?) { gotoPreview() }})
在 Kotlin 中,匿名内部类还有一个特殊之处,就是我们在使用 object 定义匿名内部类的时候,其实还可以在继承一个抽象类的同时,来实现多个接口。
1234567891011121314151617181920212223242526interface A { fun funA()}interface B { fun funB()}abstract c ...
Kotlin笔记 03 - Kotlin原理
Kotlin 的编译流程Kotlin 代码经过编译后,最终会变成 Java 字节码。Kotlin 和 Java 能够兼容的原因也在于此,Java 和 Kotlin 本质上是在用同一种语言进行沟通。
如何研究 Kotlin?将 Kotlin 转换成字节码后,再将字节码反编译成等价的 Java 代码。
123456789println("Hello world.") /* 编译 ↓ */ LDC "Hello world."INVOKESTATIC kotlin/io/ConsoleKt.println (Ljava/lang/Object;)V /* 反编译 ↓ */String var0 = "Hello world.";System.out.println(var0);
Android Studio 操作:Tools -> Kotlin -> Show Kotlin Bytecode , ...
Kotlin笔记 02 - 面向对象
类1class Person(val name: String, var age: Int)
Kotlin 定义的类,在默认情况下是 public 的
自定义属性 getter123456class Person(val name: String, var age: Int) { val isAdult get() = age >= 18// ↑// 这就是isAdult属性的getter方法}
所谓 getter,就是获取属性值的方法
如果 get() 方法内部的逻辑比较复杂,我们仍然可以像正常函数那样,带上花括号:
1234567class Person(val name: String, var age: Int) { val isAdult: Boolean get() { // do something else return age >= 18 }}
在这种情况下,编译器的自动类型推导 ...
Kotlin笔记 01 - 基础语法
变量123456/*关键字 变量类型 ↓ ↓ */var price: Int = 100; /* ↑ ↑ 变量名 变量值 */
1var price: Int = 100
Kotlin 支持类型推导,大部分情况下,我们的变量类型可以省略不写
1var price = 100 // 默认推导类型为: Int
我们应该尽可能避免使用 var,尽可能多地去使用 val
val 声明的变量,我们叫做不可变变量,它的值在初始化以后就无法再次被修改,它相当于 Java 里面的 final 变量。
var 声明的变量,我们叫做可变变量,它对应 Java 里的普通变量。
基础类型在 Kotlin 语言体系当中,是没有原始类型这个概念的。这也就意味着,在 Kotlin 里,一切都是对象。
虽然 Kotlin 在语法层面摒弃了“原始类型”,但有时候为了性能考虑,我们确实需要用“原始类型”。这时候我们应该怎么办?(TODO 后面会讲)
1val i: Double = 1.toDouble()
空安 ...
SystemServer 进程启动过程
之前的文章《浅析Android系统启动过程》简要讲解了Android系统整体启动过程,今天我们看一下其中一个重要的过程:SystemServer进程是如何启动的。
文中源码基于Android 8.0
上篇文章《Zygote进程启动过程》提到Zygote启动过程中调用了startSystemServer启动SystemServer进程,我们继续跟进里面的代码看SystemServer进程是如何启动的。
在startSystemServer中通过fork方式创建了SystemServer进程,并调用handleSystemServerProcess处理SystemServer进程,其代码如下:
123456789private static void handleSystemServerProcess( ClassLoader cl = null; if (systemServerClasspath != null) { cl = createPathClassLoader(systemServerClasspath, par ...