这份笔记是我在阅读kotlin官方文档的时候整理记录的
转载请标明出处: http://blog.csdn.net/zull_kos...
- private >>> 只在该类(以及它的成员)中可见
- protected >>> 类和它的子类可见
- internal >>> 所在的整个 module 可见。
- public >>> 任何地方可见
(一个定义为 public 的成员被包含在一个 private 修饰的类中,这个成员在这个类之外也是不可见的。)html
/** * 1.包名: */ //没必要和文件夹路径一致:源文件能够放在任意位置。 package grammar fun main(args: Array<String>) { println("2.1-->" + sum(4, 6)) //2.定义函数 println("2.2-->" + sum(3, 4, 5)) printSum(-1, 8) } /** * 2.定义函数 * */ //2.1定义一个函数接受两个 int 型参数,返回值为 int : fun sum(a: Int, b: Int): Int { return a + b } //2.2该函数只有一个表达式函数体以及一个自推导型的返回值: fun sum(a: Int, b: Int, c: Int) = a + b + c //2.3返回一个没有意义的值: fun printSum(a: Int, b: Int): Unit { println("结果: $a + $b = ${a + b}") } //2.3-Unit 的返回类型能够省略:(此方法同上 ": Unit"能够省略 fun printSumCopy(a: Int, b: Int) { println("sum of $a and $b is ${a + b}") }
val oneMillion = 1_000_000 val creditCardNumber = 1234_5678_9012_3456L val socialSecurityNumber = 999_99_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010
=== 彻底相等(包括物理地址java
== 值相等node
//多行string是由三个引号包裹的("""),不能够包含分割符但能够包含其它字符,能够经过trim-margin()函数移除空格 val text = """ |Tell me and I forget. |Teach me and I remember. |Involve me and I learn. |(Benjamin Franklin) """.trimMargin()
package grammar /* Kotlin 字符串中,$符号后面能够跟变量和函数 var a = 55 var b = 88 println("a+b=${a+b}")*/ /* 多行输入符 三个双引号 三引号的形式用来输入多行文本, 也就是说在三引号之间输入的内容将被原样保留, 之中的单号和双引号不用转义, 其中的不可见字符好比/n和/t都会被保留 """ \n""" */ /** * 1.变量 */ fun variab le() { // al a: Int = 1 // 当即初始化 val b = 2 // 推导出Int型 val c: Int // 当没有初始化值时必须声明类型 c = 3 // 赋值 println("a = $a, b = $b, c = $c") //---------------------------------------------------------- //变量 var y: Int = 5 var x = 5 // 推导出Int类型 x += 1 var z: Int z = 9 println("x = $x,y=$y,z=$z") } /** * 2.字符串模板 * */ fun txt() { var a = 1 // 使用变量名做为模板: val s1 = "a is $a" a = 2 // 使用表达式做为模板: val s2 = "${s1.replace("is", "was")}, but now is $a" println(s2) } /** * 3.使用条件表达式 * */ fun maxOf(a: Int, b: Int): Int { if (a > b) { return a } else { return b } } /** *4.使用可空变量以及空值检查 * 当空值可能出现时应该明确指出该引用可空。 * 下面的函数是当 str 中不包含整数时返回空: * */ fun printProduct(arg1: String, arg2: String) { val x = parseInt(arg1) val y = parseInt(arg2) // 直接使用 x*y 会产生错误由于它们中有可能会有空值 if (x != null && y != null) { // x 和 y 将会在空值检测后自动转换为非空值 println(x * y) } else { println("Error: '$arg1' 或者 '$arg2' 中间有的不是数字") } } fun parseInt(str: String): Int? { return str.toIntOrNull() } /** * 5.使用值检查并自动转换 * */ //使用 is 操做符检查一个表达式是不是某个类型的实例。若是对不可变的局部变量或属性进行过了类型检查,就没有必要明确转换: fun printLength(obj: Any) { println("'$obj' 字符串的长度是 ${getStringLength(obj) ?: "Error:不是字符串"} ") } fun getStringLength(obj: Any): Int? { if (obj is String) { // obj 将会在这个分支中自动转换为 String 类型 return obj.length } // obj 在种类检查外仍然是 Any 类型 return null }
使用 in 操做符检查数值是否在某个范围内git
fun inTxt(x: Int) { if (x in 1..10) { println("$x 在范围1-10之间") } else { println("$x 超出范围") } }
private fun diedai() { print("在范围内迭代:") for (u in 1..5) { print(u) } } //步进:循环中递增的倍数 private fun diedai2() { print("\n使用步进:") for (x in 1..10 step 2) { print(x) } for (x in 9 downTo 0 step 3) { print(x) } } //downTo()函数:倒序迭代//print(i) private fun RangesTxt() { for (i in 1..10) //至关于 of 1 <= i && i <= 10 for (i in 1 until 10) // i in [1, 10), 不包含:10 for (i in 1..4) print(i) // prints "1234" for (i in 4..1) print(i) // prints nothing for (i in 4 downTo 1) print(i) // prints "4321" for (i in 1..4 step 2) print(i) // prints "13" for (i in 4 downTo 1 step 2) print(i) // prints "42" //step()--能够进行任意数量的迭代,而不是每次变化都是1 for (i in 1..4 step 2) print(i) // prints "13"--遍历每次自增2 for (i in 4 downTo 1 step 2) print(i) // prints "42 }
private fun ListTxt() { val list1 = listOf("vdf", "vdrf", "vsdf") val list2 = setOf("vdf", "vdrf", "vsdf") when { //使用 in 操做符检查集合中是否包含某个对象 "vsd" in list1 -> print("cvds") } //使用lambda表达式过滤和映射集合: list1.filter { it.startsWith("a") } .sortedBy { it } .map { it.toUpperCase() } .forEach { print(it) } }
val list = listOf("a", "b", "c") //只读 list val map = mapOf("a" to 1, "b" to 2, "c" to 3) //只读map
fun foo(param: Int){ val result = if (param == 1) { "one" //结果:result="one" } else if (param == 2) { "two" //结果:result="two" } else { "three" //结果:result="three" } }
fun foo(a: Int = 0, b: String = "") {...} //注:至关于java的重载 void foo(int a){} void foo(int a,String b)
fun theAnswer() = 42 //至关于下面的写法 fun theAnswer(): Int { return 42 } //这个能够和其它习惯用语组合成高效简洁的代码。譬如说 when 表达式: fun transform(color: String): Int = when (color) { "Red" -> 0 "Green" -> 1 "Blue" -> 2 else -> throw IllegalArgumentException("Invalid color param value") }
val b: Boolean? = ... if (b == true) { ... } else { // `b` 是false或者null }
要是一个函数想返回俩个值。好比,一个对象结果,一个是排序的状态。在 Kotlin 中的一个紧凑的方案是声明 data 类并返回实例:算法
data class Result(val result: Int, val status: Status) fun function(...): Result { //... return Result(result, status) } val (result, status) = function(...)
参照相等是经过 ===
操做符判断的(不等是!==
) a===b 只有 a b 指向同一个对象是判别才成立。数据库
另外,你可使用内联函数 identityEquals()
判断参照相等:json
a.identityEquals(b) a identityEquals b
结构相等是经过 ==
判断的。像 a == b
将会翻译成:数组
a?.equals(b) ?: b === null
若是 a 不是 null 则调用 equals(Any?)
函数,不然检查 b 是否参照等于 null安全
注意彻底没有必要为优化你的代码而将 a == null
写成 a === null
编译器会自动帮你作的。多线程
//for: 经过任何提供的迭代器进行迭代。语法是下面这样的: fun loopFor() { val items = listOf("apple", "banana", "kiwi") for (str in items) { } for (index in items.indices) { println("第 $index 个是 ${items[index]}") } for (index in 0..viewGroup.getChildCount() - 1) { val view = viewGroup.getChildAt(index) view.visibility = View.VISIBLE } } //while fun loopWhile() { val items = listOf("apple", "banana", "kiwi") var index = 0 while (index < items.size) { println("第 $index 个是 ${items[index]}") index++ } //do...while do { val y = retrieveData() } while (y != null){ // y 在这是可见的 } //遍历 map/list for ((k, v) in map) { print("$k -> $v") }
//使用 in 运算符来判断集合内是否包含某实例: fun main(args: Array<String>) { val items = setOf("apple", "banana", "kiwi") when { "orange" in items -> println("juicy") "apple" in items -> println("apple is fine too") } } //使用 lambda 表达式来过滤(filter)和映射(map)集合: fun main(args: Array<String>) { val fruits = listOf("banana", "avocado", "apple", "kiwi") fruits .filter { it.startsWith("a") } .sortedBy { it } .map { it.toUpperCase() } .forEach { println(it) } }
//注意,因为 smart casts ,你能够不用另外的检查就可使用相应的属性或方法。 fun WhenTxt(obj: Any): String { return when (obj) { 1,0 -> "One or Two" //若是有分支能够用一样的方式处理的话,分支条件能够连在一块儿: s.contains("hello") -> "it's a welcome! parseInt(s) -> print("s encode x") //能够用任意表达式做为分支的条件 in 1..10 -> print("x is in the range")//甚至能够用 in 或者 !in 检查值是否值在一个范围或一个集合中: "Hello" -> "Greeting" is TextView -> obj.setText("I'm a TextView")//后台自动转型 is Long -> "Long"//也能够用 is 或者 !is 来判断值是不是某个类型。 !is String -> "不是字符串" else -> "未知格式"//也能够用来代替 if-else if 。若是没有任何参数提供,那么分支的条件就是简单的布尔表达式,当条件为真时执行相应的分支: } }
/* 咱们须要考虑何时做为一个表达式使用 --》它必需要覆盖全部分支的可能性 --》或者实现 else 分支。 不然它不会被编译成功 */ val result = when (x) { 0, 1 -> "binary" else -> "error" }
## 4.3 if 表达式 在 Kotlin 中,if 是表达式,它能够返回一个值。所以Kotlin没有三元运算符(condition ? then : else),由于if语句已经知足了效果。 ```kotlin // 传统用法 var max = a if (a < b) max = b // 带 else var max: Int if (a > b) max = a else max = b // 做为表达式:至关于--》三目运算法 val max = if (a > b) a else b
if分支能够做为块,最后一个表达式是该块的值:
val max = if (a > b){ print("Choose a") a } else{ print("Choose b") b } //若是使用If做为表达式而不是语句(例如,返回其值或将其赋值给一个变量),则须要有一个else分支。
读取操做
//逐行读取: var source = File("coffeetime-kotlin/myfile.txt") val lines = source.readLines("UTF-8") for (l in lines) { println(l) } //读取到字符串中 val contents = source.readText("UTF-8")
Kotlin 有三种结构化跳转表达式:
表达式 | 转换 |
---|---|
+a | a.plus() |
-a | a.minus() |
!a | a.not() |
a++ | a.inc() + see below |
a-- | a.dec() + see below |
表达式 | 转换 |
---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.mod(b) |
a..b | a.rangeTo(b) |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
in 和 !in他们的产生步骤是同样的,但参数顺序是相反的。
数组操做符 | 函数 |
---|---|
a[i] | a.get(i) |
a[i, j] | a.get(i, j) |
a[i_1, ..., i_n] | a.get(i_1, ... , i_n) |
a[i] = b | a.set(i, b) |
a[i,j] =b | a.set(i, j, b) |
a[i_1, ... , i_n] = b | a.set(i_1,... ,o_n,b) |
等于操做符 | 函数 |
---|---|
a == b | a?.equals(b) ?: b === null |
a != b | !(a?.equals(b) ?: b === null) |
函数方法 | 函数调用 |
---|---|
a(i) | a.invoke(i) |
a(i, j) | a.invoke(i, j) |
a(i_1, ... , i_n) | a.invoke(i_1, ..., i_n) |
在 Kotlin 类型系统中能够为空和不可为空的引用是不一样的。好比:
var a: String ="abc" a = null //编译不经过
var b: String? = "abc" b = null
val l = a.length()
val l = b.length() //错误:b 不可为空
val l = b?.length() val l = b!!.length()
#### 5.4.1.1 Elvis 操做符
val l = b.length()?: -1 //结合return与throw fun foo(node: Node): String? { val parent = node.getParent() ?: return null val name = node.getName() ?: throw IllegalArgumentException("name expected") //... }
首先,你能够检查 b
是否为空,而且分开处理下面选项:
val l = if (b != null) b.length() else -1
编译器会跟踪你检查的信息并容许在 if 中调用 length()。更复杂的条件也是能够的:
if (b != null && b.length() >0) print("Stirng of length ${b.length}") else print("Empty string")
注意只有在 b 是不可变时才能够
第二个选择就是使用安全操做符,?.
:
b?.length() //若是 b 不为空则返回长度,不然返回空。这个表达式的的类型是 Int?
安全调用在链式调用是是颇有用的。好比,若是 Bob 是一个雇员可能分配部门(也可能不分配),若是咱们想获取 Bob 的部门名做为名字的前缀,就能够这样作:
bob?.department?.head?.name
这样的调用链在任何一个属性为空都会返回空。
第三个选择是 NPE-lovers。咱们能够用 b!! ,这会返回一个非空的 b 或者抛出一个 b 为空的 NPE
val l = b !!.length()
普通的转换可能产生 ClassCastException
异常。另外一个选择就是使用安全转换,若是不成功就返回空:
val aInt: Int? = a as? Int
//一个可null的integer: val a: Int? = null //一个可nul类型,你在没有进行检查以前你是不能直接使用它。这个代码不能被编译: val a: Int? = null a.toString() //前一行代码标记为可null,而后编译器就会知道它,因此在你null检查以前你不能去使用它。 //还有一个特性是当咱们检查了一个对象的可null性,以后这个对象就会自动转型成不可null类型,这就是Kotlin编译器的智能转换: vala:Int?=null ... if(a!=null){ a.toString() } //在 if 中,a 从Int?变成了Int,因此咱们能够不须要再检查可null性而直接使用它。 //if代码以外,固然咱们又得检查处理。这仅仅在变量当前不能被改变的时候才有效,由于不然这个value可能被另外的线程修改,这时前面的检查会返回false。 //val 属性或者本地( val or var )变量。这听起来会让事情变得更多。难道咱们不得不去编写大量代码去进行可null性的检查?固然不是,首先,由于大多数时候你不须要使用null类型。Null引用没有咱们想象中的有用,当清除觉得null时你就会发现这一点。可是Kotlin也有它本身的使处理更简洁的方案。 //举个例子,咱们以下简化代码: val a: Int? = null ... a?.toString() //这里咱们使用了安全访问操做符( ? )。 //只有这个变量不是null的时候才会去执行前面的那行代码。不然,它不会作任何事情。而且咱们甚至可使用Elvis operator( ?: ): val a:Int? = null val myString = a?.toString() ?: "" //由于在Kotlin中 throw 和 return 都是表达式,他们能够用在Elvis operator操做符的右边: val myString = a?.toString() ?: return false val myString = a?.toString() ?: throw IllegalStateException() //----------------------------------------------------------------------------------------------------------------------- //而后,咱们可能会遇到这种情景,咱们肯定咱们是在用一个非null变量,可是他的类型倒是可null的。 //咱们可使用 !! 操做符来强制编译器执行可null类型时跳过限制检查: val a: Int? = null a!!.toString() //上面的代码将会被编译,可是很显然会奔溃。因此咱们要确保只能在特定的状况下使用。一般咱们能够本身选择做为解决方案。 //若是一份代码满篇都是 !! ,那就有股代码没有被正确处理的气味了。
在Kotlin中,只须要一个属性就能够了:
public class Person { var name: String = "" } ... val person = Person() person.name = "name" val name = person.name
若是没有任何指定,属性会默认使用getter和setter。固然它也能够修改成你自定义的代码,而且不修改存在的代码:
public classs Person { var name: String = "" get() = field.toUpperCase() set(value){ field = "Name: $value" } }
若是须要在getter和setter中访问这个属性自身的值,它须要建立一个 backing field 。可使用 field 这个预留字段来访问,它会被编译器找到正在使用的并自动建立。须要注意的是,若是咱们直接调用了属性,那咱们会使用setter和getter,而不是直接访问这个属性。 backing field 只能在属性访问器内访问。
就如在前面章节提到的,当操做Java代码的时候,Kotlin将容许使用属性的语法去访问在Java文件中定义的getter/setter方法。编译器会直接连接到它原始的getter/setter方法。因此当咱们直接访问属性的时候不会有性能开销。
//首先要编写一个 OnClickListener 接口: public interface OnClickListener { void onClick(View v); }
//编写一个匿名内部类去实现这个接口 view.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show(); } })
//把上面的代码转换成Kotlin(使用了Anko的toast函数): view.setOnClickListener(object : OnClickListener { override fun onClick(v: View) { toast("Click") } }
//Kotlin容许Java库的一些优化,Interface中包含单个函数能够被替代为一个函数。若是咱们这么去定义了,它会正常执行: fun setOnClickListener(listener: (View) -> Unit) //一个lambda表达式经过参数的形式被定义在箭头的左边(被圆括号包围),而后在箭头的右边返回结果值。在这个例子中,咱们接收一个View,而后返回一个Unit(没有东西)。因此根据这种思想,咱们能够把前面的代码简化成这样: view.setOnClickListener({ view -> toast("Click") }) //当咱们定义了一个方法,咱们必须使用大括号包围,而后在箭头的左边指定参数,在箭头的右边返回函数执行的结果。若是左边的参数没有使用到,咱们甚至能够省略左边的参数: view.setOnClickListener({ toast("Click") }) //若是这个函数的最后一个参数是一个函数,咱们能够把这个函数移动到圆括号外面: view.setOnClickListener() { toast("Click") } //而且,最后,若是这个函数只有一个参数,咱们能够省略这个圆括号: view.setOnClickListener { toast("Click")} //比原始的Java代码简短了5倍多。
在Kotlin的标准库中有一系列的标准委托。它们包括了大部分有用的委托,可是咱们也能够建立咱们本身的委托。
它包含一个lambda,当第一次执行 getValue 的时候这个lambda会被调用,因此这个属性能够被延迟初始化。以后的调用都只会返回同一个值。这是很是有趣特性, 当咱们在它们第一次真正调用以前不是必须须要它们的时候。咱们能够节省内存,在这些属性真正须要前不进行初始化。
class App : Application() { val database: SQLiteOpenHelper by lazy { MyDatabaseHelper(applicationContext) } override fun onCreate() { super.onCreate() val db = database.writableDatabase } } //在这个例子中,database并无被真正初始化,直到第一次调用 onCreate 时。 //在那以后,咱们才确保applicationContext存在,而且已经准备好能够被使用了。 //lazy 操做符是线程安全的。若是你不担忧多线程问题或者想提升更多的性能,你也可使用 lazy(LazyThreadSafeMode.NONE){ ... }
这个委托会帮咱们监测咱们但愿观察的属性的变化。当被观察属性的 set 方法被调用的时候,它就会自动执行咱们指定的lambda表达式。因此一旦该属性被赋了新的值,咱们就会接收到被委托的属性、旧值和新值。
//这个例子展现了,一些咱们须要关心的ViewMode,每次值被修改了,就会保存它们到数据库。 class ViewModel(val db: MyDatabase) { var myProperty by Delegates.observable("") { d, old, new -> db.saveChanges(this, new) } }
这是一个特殊的 observable ,它让你决定是否这个值须要被保存。它能够被用于在真正保存以前进行一些条件判断。
//这个委托只容许在新的值是正数的时候执行保存。在lambda中,最后一行表示返回值。你不须要使用return关键字(实质上不能被编译)。 var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }
有时候咱们须要在某些地方初始化这个属性,可是咱们不能在构造函数中肯定,或者咱们不能在构造函数中作任何事情。第二种状况在Android中很常见:在Activity、fragment、service、receivers……不管如何,一个非抽象的属性在构造函数执行完以前须要被赋值。为了给这些属性赋值,咱们没法让它一直等待到咱们但愿给它赋值的时候。咱们至少有两种选择方案。第一种就是使用可null类型而且赋值为null,直到咱们有了真正想赋的值。可是咱们就须要在每一个地方无论是不是null都要去检查。若是咱们肯定这个属性在任何咱们使用的时候都不会是null,这可能会使得咱们要编写一些必要的代码了。第二种选择是使用 notNull 委托。它会含有一个可null的变量并会在咱们设置这个属性的时候分配一个真实的值。若是这个值在被获取以前没有被分配,它就会抛出一个异常。
这个在单例App这个例子中颇有用:
class App : Application() { companion object { var instance: App by Delegates.notNull() } override fun onCreate() { super.onCreate() instance = this } }
//若是至少有一个元素符合给出的判断条件,则返回true。 val list = listOf(1, 2, 3, 4, 5, 6) assertTrue(list.any { it % 2 == 0 }) assertFalse(list.any { it > 10 })
//若是所有的元素符合给出的判断条件,则返回true。 assertTrue(list.all { it < 10 }) assertFalse(list.all { it % 2 == 0 })
//返回符合给出判断条件的元素总数。 assertEquals(3, list.count { it % 2 == 0 })
//在一个初始值的基础上从第一项到最后一项经过一个函数累计全部的元素。 assertEquals(25, list.fold(4) { total, next -> total + next })
//与 fold 同样,可是顺序是从最后一项到第一项。 assertEquals(25, list.foldRight(4) { total, next -> total + next })
//遍历全部元素,并执行给定的操做。 list.forEach { println(it) }
//与 forEach ,可是咱们同时能够获得元素的index。 list.forEachIndexed { index, value -> println("position index contains a value") }
//返回最大的一项,若是没有则返回null。 assertEquals(6, list.max())
//根据给定的函数返回最大的一项,若是没有则返回null。 assertEquals(1, list.maxBy { -it })// The element whose negative is greater
//返回最小的一项,若是没有则返回null。 assertEquals(1, list.min())
//根据给定的函数返回最小的一项,若是没有则返回null。 assertEquals(6, list.minBy { -it })// The element whose negative is smaller
//若是没有任何元素与给定的函数匹配,则返回true。 assertTrue(list.none { it % 7 == 0 })// No elements are divisible by 7
//与 fold 同样,可是没有一个初始值。经过一个函数从第一项到最后一项进行累计。 assertEquals(21, list.reduce { total, next -> total + next })
//与 reduce 同样,可是顺序是从最后一项到第一项。 assertEquals(21, list.reduceRight { total, next -> total + next })
//返回全部每一项经过函数转换以后的数据的总和。 assertEquals(3, list.sumBy { it % 2 })
val listIntTotal = listOf(1, 2, 3, 4, 5, 6) val listStrTotal = listOf("yes", "no", "sure") fun main(args: Array<String>) { //1.any 若是至少有一个元素符合给出的判断条件,则返回true println(listIntTotal.any { it % 2 == 0 })//true println("--------------any1 -------------------------------") println(listIntTotal.any { it > 10 })//false println("--------------any2 -------------------------------") //2.all 若是所有的元素符合给出的判断条件,则返回true println(listIntTotal.all { it < 10 })//true println("--------------all1 -------------------------------") println(listIntTotal.all { it % 2 == 0 })//false println("--------------all2 -------------------------------") //3.count 返回符合给出判断条件的元素总数 println(listIntTotal.count { it % 2 == 0 })//3 println("--------------count-------------------------------") //4.fold 在一个初始值的基础上从第一项到最后一项经过一个函数累计全部的元素 //其实fold 就是折叠的意思,把一个集合的元素折叠起来的并获得一个最终的结果 //从4开始,1+4,2+5,3+7,4+10,5+14,6+19=25 println(listIntTotal.fold(4) { total, next -> total + next })//25 println("--------------fold1-------------------------------") //将int 转换为字符串 val r1 = listIntTotal.fold(StringBuilder()) { strBuilder, it -> strBuilder.append(it).append(",") } println(r1.toString() is String) println("--------------fold2-------------------------------") //5.foldRight 与 fold 同样,可是顺序是从最后一项到第一项 //从4开始,4+6,10+5,15+4,19+3,22+2,24+1=25 println(listIntTotal.foldRight(4) { total, next -> total + next })//25 println("--------------foldRight-------------------------------") //6.reduce 与 fold 同样,可是没有一个初始值。经过一个函数从第一项到最后一项进行累计 println(factorial(5))//120 println("--------------factorial-------------------------------") println(listIntTotal.reduce { total, next -> total + next })//21 println("--------------reduce-------------------------------") println(listIntTotal.reduceRight { i, acc -> i + acc })//21 println("--------------reduceRight-------------------------------") //7.forEach listStrTotal.forEach { println(it) } println("--------------forEach-------------------------------") //与forEach相似 可是咱们同时能够获得元素的index listStrTotal.forEachIndexed { index, s -> println("$index $s") } println("--------------forEachIndexed-------------------------------") listStrTotal.forEachWithIndex { i, s -> println("$i $s") } println("--------------forEachWithIndex-------------------------------") listStrTotal.forEachReversedWithIndex { i, s -> println("$i $s") } println("--------------forEachReversedWithIndex-------------------------------") listStrTotal.forEachReversed { println(it) } println("--------------forEachReversed-------------------------------") listStrTotal.forEachByIndex { println(it) } println("--------------forEachByIndex-------------------------------") //8.max 返回最大的一项,若是没有则返回null println(listIntTotal.max()) println("--------------max-------------------------------") println(listIntTotal.maxBy { -(4 - it * 8) }) println("--------------maxBy-------------------------------") //9.min 返回最小的一项,若是没有则返回null println(listIntTotal.min()) println("--------------min-------------------------------") println(listIntTotal.minBy { -(4 - it * 8) }) println("--------------minBy-------------------------------") //10.none 若是没有任何元素与给定的函数匹配,则返回true。 println(listIntTotal.none())//false println("--------------none-------------------------------") println(listIntTotal.none { it % 3 == 0 })//false println("--------------none-------------------------------") //11.sumBy 返回全部每一项经过函数转换以后的数据的总和 println(listIntTotal.sumBy { it % 2 })//3 println("--------------sumBy-------------------------------") }
//返回包含去掉前n个元素的全部元素的列表。 assertEquals(listOf(5, 6), list.drop(4))
//返回根据给定函数从第一项开始去掉指定元素的列表。 assertEquals(listOf(3, 4, 5, 6), list.dropWhile { it < 3 })
//返回根据给定函数从最后一项开始去掉指定元素的列表。 assertEquals(listOf(1, 2, 3, 4), list.dropLastWhile { it > 4 })
//过滤全部符合给定函数条件的元素。 assertEquals(listOf(2, 4, 6), list .ilter { it % 2 == 0 })
//过滤全部不符合给定函数条件的元素。 assertEquals(listOf(1, 3, 5), list.filterNot { it % 2 == 0 })
//过滤全部元素中不是null的元素。 assertEquals(listOf(1, 2, 3, 4), listWithNull.filterNotNull())
//过滤一个list中指定index的元素。 assertEquals(listOf(2, 4, 5), list.slice(listOf(1, 3, 4)))
//返回从第一个开始的n个元素。 assertEquals(listOf(1, 2), list.take(2))
//返回从最后一个开始的n个元素 assertEquals(listOf(5, 6), list.takeLast(2))
//返回从第一个开始符合给定函数条件的元素。// assertEquals(listOf(1, 2), list.takeWhile { it < 3 })
val listIntFilter = listOf(1, 2, 3, 4, 5, 6) fun main(args: Array<String>) { //1.drop 返回包含去掉前n个元素的全部元素的列表 (listIntFilter.drop(3)).forEach { println(it) }//4,5,6 println("--------------drop -------------------------------") //2.filter 过滤全部符合给定函数条件的元素 (listIntFilter.filter { it % 2 == 0 }).forEach { println(it) }//2,4,6 println("--------------filter -------------------------------") //3.filterNot 过滤全部不符合给定函数条件的元素 (listIntFilter.filterNot { it % 2 == 0 }).forEach { println(it) }//1,3,5 println("--------------filterNot -------------------------------") //4.slice 过滤掉非指定下标的元素,即保留下标对应的元素过滤List中指定下标的元素(好比这里只保留下标为1,3,4的元素),当过滤list中有元素值大于目标List大小时会出现异常 (listIntFilter.slice(listOf(1, 4)).forEach { println(it) })//2,5 println("--------------slice -------------------------------") //5.take 返回从第一个开始的n个元素 (listIntFilter.take(3)).forEach { println(it) }//1,2,3 println("--------------take -------------------------------") //6.takeLast 返回从最后一个开始的n个元素 (listIntFilter.takeLast(3)).forEach { println(it) }//4,5,6 println("--------------takeLast -------------------------------") //7.takeWhile 返回从第一个开始符合给定函数条件的元素 (listIntFilter.takeWhile { it < 3 }).forEach { println(it) }//1,2 println("--------------takeWhile -------------------------------") }
//遍历全部的元素,为每个建立一个集合,最后把全部的集合放在一个集合中。 assertEquals(listOf(1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7), list.flatMap { listOf(it, it + 1) })
//返回一个根据给定函数分组后的map。 assertEquals(mapOf("odd" to listOf(1, 3, 5), "even" to listOf(2, 4, 6)), list.groupBy { if (it % 2 == 0) "even" else "odd" })
//返回一个每个元素根据给定的函数转换所组成的List。 assertEquals(listOf(2, 4, 6, 8, 10, 12), list.map { it * 2 })
//返回一个每个元素根据给定的包含元素index的函数转换所组成的List。 assertEquals(listOf (0, 2, 6, 12, 20, 30), list.mapIndexed { ind ex, it -> index * it })
//返回一个每个非null元素根据给定的函数转换所组成的List。 assertEquals(listOf(2, 4, 6, 8), listWithNull.mapNotNull { it * 2 })
val listIntMap = listOf(1, 2, 3, 4, 5, 6) val listStrMap = listOf("y,s", "n,o", "su,e") fun main(args: Array<String>) { //1.flatMap 遍历全部的元素,为每个建立一个集合,最后把全部的集合放在一个集合中 (listStrMap.flatMap { it.split(",") }).forEach { print(it) } (listStrMap.flatMap { it.split(",") }).map { println(it) } val list = listOf( 1..20, 2..5 ) (list.flatMap { it }).forEach { println(it) } (list.flatMap { it.map { it * 2 } }).forEach { println(it) } println("--------------flatMap -------------------------------") //2.groupBy 返回一个根据给定函数分组后的map (listIntMap.groupBy { if (it > 4) "大于4" else "小于4" }).forEach { t, u -> println("$t $u") } println("--------------groupBy -------------------------------") //3.map 返回一个每个元素根据给定的函数转换所组成的List (listIntMap.map { it * 2 }).forEach { println(it) } println("--------------map -------------------------------") //4.mapIndexed 返回一个每个元素根据给定的包含元素index的函数转换所组成的List listIntMap.mapIndexed { index, i -> println("$index $i") } println("--------------mapIndexed -------------------------------") }
//若是指定元素能够在集合中找到,则返回true。 assertTrue(list.contains(2))
//返回给定index对应的元素,若是index数组越界则会抛出 IndexOutOfBoundsException 。 assertEquals(2, list.elementAt(1))
//返回给定index对应的元素,若是index数组越界则会根据给定函数返回默认值。 assertEquals(20, list.elementAtOrElse(10, { 2 * it }))
//返回给定index对应的元素,若是index数组越界则会返回null。 assertNull(list.elementAtOrNull(10))
//返回符合给定函数条件的第一个元素。 assertEquals(2, list.first { it % 2 == 0 })
//返回符合给定函数条件的第一个元素,若是没有符合则返回null。 assertNull(list.firstOrNull { it % 7 == 0 })
//返回指定元素的第一个index,若是不存在,则返回 -1 。 assertEquals(3, list.indexOf(4))
//返回第一个符合给定函数条件的元素的index,若是没有符合则返回 -1 。 assertEquals(1, list.indexOfFirst { it % 2 == 0 })
//返回最后一个符合给定函数条件的元素的index,若是没有符合则返回 -1 。 assertEquals(5, list.indexOfLast { it % 2 == 0 })
//返回符合给定函数条件的最后一个元素。 assertEquals(6, list.last { it % 2 == 0 })
返回指定元素的最后一个index,若是不存在,则返回 -1 。
//返回符合给定函数条件的最后一个元素,若是没有符合则返回null。 val list = listOf(1, 2, 3, 4, 5, 6) assertNull(list.lastOrNull { it % 7 == 0 })
//返回符合给定函数的单个元素,若是没有符合或者超过一个,则抛出异常。 assertEquals(5, list.single { it % 5 == 0 })
//返回符合给定函数的单个元素,若是没有符合或者超过一个,则返回null。 assertNull(list.singleOrNull { it % 7 == 0 })
val listIntElement = listOf(1, 2, 3, 4, 5, 6) fun main(args: Array<String>) { //1.contains 若是指定元素能够在集合中找到,则返回true println(listIntElement.contains(3))//true println("--------------contains -------------------------------") //2.elementAt 返回给定index对应的元素,若是index数组越界则会抛出 IndexOutOfBoundsException println(listIntElement.elementAt(2))//3 println("--------------elementAt -------------------------------") //3.elementAtOrElse 返回给定index对应的元素,若是index数组越界则会根据给定函数返回默认值 println(listIntElement.elementAtOrElse(3, { "没有哦" }))//4 println(listIntElement.elementAtOrElse(8, { "没有哦" }))//没有哦 println("--------------elementAtOrElse -------------------------------") //4.first 返回符合给定函数条件的第一个元素 println(listIntElement.first())//1 println(listIntElement.first{ it % 3 == 0 })//3 println("--------------first -------------------------------") //5.indexOf 返回指定元素的第一个index,若是不存在,则返回 -1 println(listIntElement.indexOf(3))//2 println(listIntElement.indexOf(8))//-1 println("--------------indexOf -------------------------------") //6.indexOfFirst 返回第一个符合给定函数条件的元素的index,若是没有符合则返回 -1 println(listIntElement.indexOfFirst{ it % 3 == 0 })//2 println("--------------indexOfFirst -------------------------------") //同理还有indexOfLast,表示返回最后一个符合给定函数条件的元素的index,若是没有符合则返回 -1 println(listIntElement.indexOfLast{ it % 3 == 0 })//5 println("--------------indexOfLast -------------------------------") //7.last 返回符合给定函数条件的最后一个元素 println(listIntElement.last())//6 println("--------------last -------------------------------") //8.lastIndexOf 返回指定元素的最后一个index,若是不存在,则返回 -1 println(listIntElement.lastIndexOf(2))//1 若是list为(1, 2, 3, 4, 2, 5, 6)则结果为4 println("--------------lastIndexOf -------------------------------") }
//把两个集合合并成一个新的,相同index的元素经过给定的函数进行合并成新的元素做为新的集合的一个元素,返回这个新的集合。 //新的集合的大小由最小的那个集合大小决定。 val list = listOf(1, 2, 3, 4, 5, 6) val listRepeated = listOf(2, 2, 3, 4, 5, 5, 6) assertEquals(listOf(3, 4, 6, 8, 10, 11), list.merge(listRepeated ) { it1, it2 -> it1 + it2 })
//把一个给定的集合分割成两个,第一个集合是由原集合每一项元素匹配给定函数条件返回 true 的元素组成, //第二个集合是由原集合每一项元素匹配给定函数条件返回 false 的元素组成。 assertEquals( Pair(listOf(2, 4, 6), listOf(1, 3, 5)) , list.partition { it % 2 == 0 } )
//返回一个包含原集合和给定集合中全部元素的集合,由于函数的名字缘由,咱们可使用 + 操做符。 assertEquals( listOf(1, 2, 3, 4, 5, 6, 7, 8) , list + listOf(7, 8) )
//返回由 pair 组成的List,每一个 pair 由两个集合中相同index的元素组成。这个返 回的List的大小由最小的那个集合决定。 assertEquals( listOf(Pair(1, 7), Pair(2, 8)) , list.zip(listOf(7, 8)) )
//从包含pair的List中生成包含List的Pair。 assertEquals( Pair(listOf(5, 6), listOf(7, 8)) , listOf(Pair(5, 7), Pair(6, 8)).unzip() )
val listIntProduct1 = listOf(1, 2, 3, 4, 5, 6) val listIntProduct2 = listOf(3, 5, 7, 9) fun main(args: Array<String>) { //1.partition 把一个给定的集合分割成两个,第一个集合是由原集合每一项元素匹配给定函数条件返回 true 的元素组成,第二个集合是由原集合每一项元素匹配给定函数条件返回 false 的元素组成 println(listIntProduct1.partition { it > 3 })//([4, 5, 6], [1, 2, 3]) println("--------------partition -------------------------------") //2.plus 合并两个List,能够用”+”替代 println(listIntProduct1.plus(listIntProduct2))//[1, 2, 3, 4, 5, 6, 3, 5, 7, 9] println("--------------plus -------------------------------") //3.zip 两个集合按照下标组合成一个个的Pair塞到集合中返回 println(listIntProduct1.zip(listIntProduct2))//[1, 2, 3, 4, 5, 6, 3, 5, 7, 9] println("--------------zip -------------------------------") //merge的替代方法,把两个集合,按照相同下标,合成新的元素,合成的集合大小由最小的集合决定 println(listIntProduct1.zip(listIntProduct2) { it1, it2 -> it1 + it2 })//[4, 7, 10, 13] println("--------------zip 替代 merge-------------------------------") }
//返回一个与指定list相反顺序的list。 val unsortedList = listOf(3, 2, 7, 5) assertEquals(listOf(5, 7, 2, 3), unsortedList.reverse())
//返回一个天然排序后的list。 assertEquals(listOf(2, 3, 5, 7), unsortedList.sort())
//返回一个根据指定函数排序后的list。 assertEquals(listOf(3, 7, 2, 5), unsortedList.sortBy { it % 3 })
//返回一个降序排序后的List。 assertEquals(listOf(7, 5, 3, 2), unsortedList.sortDescending())
//返回一个根据指定函数降序排序后的list。 assertEquals( listOf(2, 5, 7, 3), unsortedList.sortDescendingBy { it % 3 })
val listIntOrder1 = listOf(1, 2, 3, 4, 5, 6) val listIntOrder2 = listOf(5, 2, 4, 8, 1, 6) fun main(args: Array<String>) { //1.reverse 返回一个与指定list相反顺序的list println(listIntOrder1.reversed())//[6, 5, 4, 3, 2, 1] println("--------------reversed-------------------------------") //2.sorted 返回一个天然排序后的list println(listIntOrder2.sorted())//[1, 2, 4, 5, 6, 8] println("--------------sorted-------------------------------") //3.sortedBy 返回一个根据指定函数排序后的list println(listIntOrder1.sortedBy { it * 2 })//[1, 2, 4, 5, 6, 8] println("--------------sortedBy-------------------------------") //4.sortDescending 返回一个降序排序后的List println(listIntOrder1.sortedDescending())//[6, 5, 4, 3, 2, 1] println("--------------sortedDescending-------------------------------") //5.sortDescendingBy 返回一个根据指定函数降序排序后的list println(listIntOrder1.sortedByDescending { it % 2 })//[1, 3, 5, 2, 4, 6] println("--------------sortedByDescending-------------------------------") }
嵌套类
//在Java中,能够在类的里面再定义类。若是它是一个一般的类,它不能去访问外部类的成员(就如Java中的static): class Outer { private val bar: Int = 1 class Nested { fun foo() = bar//编译不经过 } }
内部类
//若是须要去访问外部类的成员,咱们须要用 inner 声明这个类: class Outer { private val bar: Int = 1 inner class Inner{ fun foo() = bar//没问题 } } val demo = Outer().Inner().foo() // == 1
1.Kotlin提供了枚举(enums)的实现: enum class Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY,HURSDAY, FRIDAY, SATURDAY } 2.枚举能够带有参数: enum class Icon(val id: Int,var desc:String) { UO(1,"aa"), Search(2,"bb"), Cast(3,"cc") } val searchIconRes = Icon.Search.id//结果:2 var a = Icon.Search.desc//结果:"bb" 3.枚举能够经过 String 匹配名字来获取,咱们也能够获取包含全部枚举的 Array ,因此咱们能够遍历它。 val search: Icon = Icon.valueOf("Search") val iconList: Array<Icon> = Icon.values() iconList.forEach {print("$it")}//结果:UOSearchCast 4.每个枚举都有一些函数来获取它的名字、声明的位置: val searchName: String = Icon.SEARCH.name() val searchPosition: Int = Icon.SEARCH.ordinal() println(Icon.Search.name+"---"+Icon.Search.ordinal)//结果:Search---1 //枚举根据它的顺序实现了Comparable接口,因此能够很方便地把它们进行排序。
sealed class Option<out T> { class Some<out T> : Option<T>() object None : Option<Nothing>() } //有一件关于密封类很不错的事情是当咱们使用 when 表达式时,咱们能够匹配全部选项而不使用 else分支: val result = when (option) { is Option.Some<*> -> "Contains a value" is Option.None -> "Empty" }
1.抛出异常的方式与Java很相似: throw MyException("Exception message") 2.try 表达式也是相同的: try{ // 一些代码 }catch (e: SomeException) { // 处理 }finally { // 可选的finally块 } 3.在Kotlin中, throw 和 try 都是表达式,这意味着它们能够被赋值给一个变量。 //这个在处理一些边界问题的时候确实很是有用: val s = when(x){ is Int -> "Int instance" is String -> "String instance" else -> throw UnsupportedOperationException("Not valid type" ) } 3.1.或者 val s = try { x as String } catch(e: ClassCastException) { null }
1.写法 class Box<T>(t: T){ var value = t } 2.一般来讲,建立一个这样类的实例,须要提供类型参数: val box: Box<Int> = Box<Int>(1) 3.可是若是泛型能够推断(好比:构造函数推断),则能够省略 val box = Box(1)//1是 Int 型,所以编译器会推导出咱们调用的是 Box<Int>
interface Collection<E> ... { void addAll(Colletion<? extend E> items); } void copyAll(Collection<Object> to, Collection<String> from) { to.addAll(from); // 警告:!!! Would not compile with the naive declaration of addAll: //Collection<String> 继承自 Collection<Object> } 2.假若有个范型接口Source<T>,没有任何接收 T 做为参数的方法,惟一的方法就是返回 T: interface Source<T> { T nextT(); } 3.存储一个Source<String>的实例引用给一个类型为 Source<Object> 是安全的,但java并不知道 void demo(Source<String> strs) { Source<Object> objects = strs; // !!! 编译不经过 }
声明处变型
1.经过注解类型参数 T
的来源,来确保它仅从 Source<T>
成员中返回(生产),并从不被消费。 kotlin提供 out 修饰符:
2.通常原则是:当一个类 C
的类型参数 T
被声明为 out 时,它就只能出如今 C
的成员的输出位置,结果是 C<Base>
能够安全地做为 C<Derived>
的超类。
3.out
修饰符被称之为变型注解,但因为同处与类型参数声明处,咱们称之为声明处变型
。这与 Java 中的使用处变型相反。
//声明处变型:out abstract class Source<out T> { abstract fun nextT(): T } fun demo(strs: Source<String>) { val objects: Source<Any> = strs }
4.in----out以外Kotlin 又补充了一个变型注释,它接受一个类型参数逆变
//声明处变型:in abstract class Comparable<in T> { abstract fun compareTo(other: T): Int } fun demo(x: Comparable<Number>) { x.compareTo(1.0) // 1.0 类型:Double, 属于Number的子类 val y: Comparable<Double> = x } //消费者 in, 生产者 out! (in 和 out 的使用参照C#
使用处变型
//使用处变型:类型投影 1.声明类型参数 T 为 out 很方便,并且能够避免在使用出子类型的麻烦,但有些类 不能 限制它只返回 T class Array<T>(val size: Int) { fun get(index: Int): T { /* ... */ } fun set(index: Int, value: T) { /* ... */ } } 2.声明类型参数 T 为 out 很方便,并且能够避免在使用出子类型的麻烦,但有些类 不能 限制它只返回 T //该函数做用是复制 array fun copy(from: Array<Any>, to: Array<Any>) { assert(from.size == to.size) for (i in from.indices) to[i] = from[i] } 3.遇到了一样的问题 Array<T> 中的T 是不可变型的,所以 Array<Int> 和 Array<Any> 互不为对方的子类,致使复制失败。 val ints: Array<Int> = arrayOf(1, 2, 3) val any = Array<Any>(3) { "" } copy(ints, any) // 抛异常:ClassCastException (Array<Any>, Array<Any>) 4.类型投影 fun copy(from: Array<out Any>, to: Array<Any>) { // 这里的from不是一个简单的 array, 而是一个投影 //只能调用那些返回类型参数 T 的方法,在这里意味着只能调用get()。相似 Java 中Array<? extends Object> } 5.用in作投影的写法 fun fill(dest: Array<in String>, value: String) { // Array<in String> 对应 Java 中的 Array<? super String> //fill()函数能够接受任何CharSequence 类型或 Object类型的 array 。 }
函数也能够像类同样有类型参数。类型参数在函数名以前: fun <T> singletonList(item: T): List<T> { // ... } fun <T> T.basicToString() : String { // extension function }
最经常使用的类型约束是上界,在 Java 中对应 extends关键字:
fun <T : Comparable<T>> sort(list: List<T>) { // 冒号后面指定的类型就是上界:只有 Comparable<T>的子类型才能够取代 T 好比: }
代理模式
1.代理模式 给实现继承提供了很好的代替方式, 因此并不须要什么样板代码 2.Derived 类能够继承 Base 接口而且指定一个对象代理它所有的公共方法: interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fun print() { printz(x) } } class Derived(b: Base) : Base by b //关键字:by fun main() { val b = BaseImpl(10) Derived(b).print() } 3.在 Derived 的父类列表中的 by 从句会将 b 存储在 Derived 内部对象,而且编译器会生成 Base 的全部方法并转给 b。
代理属性
1.注解声明:声明注解须要在类前面使用 annotation 关键字 annotation class fancy 2.用法 @fancy class Foo { @fancy fun baz(@fancy foo: Int): Int { return (@fancy 1) } } 2.1.在多数情形中 @ 标识是可选的。只有在注解表达式或本地声明中才必须: fancy class Foo { fancy fun baz(fancy foo: Int): Int { @fancy fun bar() { ... } return (@fancy 1) } } 2.2.若是要给构造函数注解,就须要在构造函数声明时添加 constructor 关键字,而且须要在前面添加注解:+ class Foo @inject constructor (dependency: MyDependency) 2.3.也能够注解属性访问者: class Foo { var x: MyDependency?=null @inject set } 3.构造函数 //注解能够有带参数的构造函数。 annotation class special(val why: String) special("example") class Foo {} 4.Lambdas //注解也能够用在 Lambda 中。这将会应用到 lambda 生成的 invoke() 方法。这对 Quasar框架颇有用,在这个框架中注解被用来并发控制 annotation class Suspendable val f = @Suspendable { Fiber.sleep(10) } 5.java 注解在 kotlin 中是彻底兼容的:
1.最基本的反射特性就是获得运行时的类引用。要获取引用并使之成为静态类可使用字面类语法: val c = MyClass::class 2.函数引用 //当有一个像下面这样的函数声明时: fun isOdd(x: Int) =x % 2 !=0 //能够经过 isOdd(5) 轻松调用,一样咱们也能够把它做为一个值传递给其它函数,操做符:: val numbers = listOf(1, 2, 3) println(numbers.filter( ::isOdd) ) //prints [1, 3] 3.这里 ::isOdd 是是一个函数类型的值 (Int) -> Boolean 4.属性引用:访问顶级类的属性,也可使用 :: 操做符 var x = 1 fun main(args: Array<String>) { println(::x.get()) ::x.set(2)//::x 表达式评估为 KProperty<Int> 类型的属性 println(x) } 5.访问一个类的属性成员 class A(val p: Int) fun main(args: Array<String>) { val prop = A::p println(prop.get(A(1))) // prints "1" } 6.与 java 反射调用 import kotlin.reflect.jvm.* class A(val p: Int) fun main(args: Array<String>) { println(A::p.javaGetter) // 打印 "public final int A.getP()" println(A::p.javaField) // 打印 "private final int A.p" } 7.构造函数引用 //构造函数能够像方法或属性那样引用。只须要使用 :: 操做符并加上类名。 //下面的函数是一个没有参数而且返回类型是 Foo: calss Foo fun function(factory : () -> Foo) { val x: Foo = factory() } //还能够像下面这样使用: function(:: Foo)
其余:略...
dynamic
1.dynamic 类型关闭了 kotlin 的类型检查: val dyn: dynamic = ... 2.dynamic 最奇特的特性就是能够在 dynamic 变量上调用任何属性或任何方法 dyn.whatever(1, "foo", dyn) dyn.whatever(*array(1, 2, 3)) 3.待续...
fun factorial(num: Int): BigInteger { if (num == 0) return BigInteger.valueOf(1L) return BigInteger.valueOf(num.toLong()).times(factorial(num - 1)) } fun main(args: Array<String>) { println(factorial(50000))}
//尾递归:其实是把递归编译成了迭代 class Result(var value: BigInteger = BigInteger.valueOf(1)) tailrec fun factorialWei(num: Int, result: Result) { if (num == 0) { result.value = result.value.times(BigInteger.valueOf(1L)) } else { result.value = result.value.times(BigInteger.valueOf(num.toLong())) factorialWei(num - 1, result) } } fun main(args: Array<String>) { val result = Result() factorialWei(50000,result) println(result.value) }
1.线程安全,检查2次
1.Java写法 class LazyDoubleCheckJava { /** * java-5以后新增的关键字volatile * 可以保证方法的调用有序进行 * */ private static volatile LazyDoubleCheckJava instance; private LazyDoubleCheckJava() { } public static LazyDoubleCheckJava getInstance() { if (instance == null) { synchronized (LazyDoubleCheckJava.class) { if (instance == null) { //初始化时分为实例化,赋值2步,尽管咱们把这一步写成下面的语句 //但java虚拟机并不保证其余线程【眼中】这两步的顺序到底是怎么样的 //java5以后新增的关键字volatile instance = new LazyDoubleCheckJava(); }}} return instance; }} 2.kotlin写法 class LazyDoubleCheckKotlin private constructor() { companion object { val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { LazyDoubleCheckKotlin() } ------------------------------------------------------------------------- //另外一种等价的写法 private @Volatile var instance2: LazyDoubleCheckKotlin? = null fun getInstacne(): LazyDoubleCheckKotlin { if (instance2 == null) { synchronized(this) { if (instance2 == null) { instance2 = LazyDoubleCheckKotlin() }}} return instance2!! }}}
2.静态内部类
1.Java写法 class LazyStaticInnerJava { private LazyStaticInnerJava() { } private static class Holder { private static LazyStaticInnerJava instance = new LazyStaticInnerJava(); } public static LazyStaticInnerJava getInstance() { return Holder.instance; } } 2.kotlin写法 class LazyStaticInnerKotlin { companion object { fun getInstance() = Hoder.instance } private object Hoder { val instance = LazyStaticInnerKotlin() } }
3.最常规写法
1.Java写法 class PlainOldSingletonJava { private static PlainOldSingletonJava java; private PlainOldSingletonJava() { } public static PlainOldSingletonJava getInstance() { return java; } } 2.kotlin写法 object PlainOldSingletonKotlin { }
4.懒加载-非线程安全
1.Java写法 class LazyNoThreadSafeJava { private static LazyNoThreadSafeJava java; private LazyNoThreadSafeJava() { } public static LazyNoThreadSafeJava getInstance() { if (java == null) { java = new LazyNoThreadSafeJava(); } return java; } } 2.kotlin写法 class LazyNoThreadSafeKotlin { //使用kotlin封装方法 companion object { val instance by lazy(LazyThreadSafetyMode.NONE) { LazyNoThreadSafeKotlin() } } //下面是另外一种等价的写法,获取单例使用get方法 private var instance2: LazyNoThreadSafeKotlin? = null fun getInstance(): LazyNoThreadSafeKotlin { if (instance2 == null) { instance2 = singleton.LazyNoThreadSafeKotlin() } return instance2!! } }
5.懒加载-线程安全
1.Java写法 class LazyThreadSafeJava { private static LazyThreadSafeJava java; private LazyThreadSafeJava() { } public static synchronized LazyThreadSafeJava getInstance() { if (java == null) { java = new LazyThreadSafeJava(); } return java; } } 2.kotlin写法 class LazyThreadSafeKotlin { //下面是另外一种等价的写法,获取单例使用get方法 private var instance2: LazyThreadSafeKotlin? = null @Synchronized fun getInstance(): LazyThreadSafeKotlin { if (instance2 == null) { instance2 = singleton.LazyThreadSafeKotlin() } return instance2!! } }