参考链接
Kotlin官方文档
https://kotlinlang.org/docs/home.html
本系列为参考Kotlin中文文档
https://download.csdn.net/download/u011109881/21418027
整理的笔记 不记得原pdf下载地址了
第一章 开始
知识点
1.kotlin主函数入口 kotlin方法
2.变量?string 模板?条件表达式?空值检测?类型检测与自动类型转换?使用For循环??使用while循环?使用when表达式
笔记
package com.example.lib.d01start
// 将Kotlin转为Java步骤:
// Tools → Kotlin icon Kotlin → Show Kotlin Bytecode
// Decompile
// 会将Kotlin Code的二进制转为Java Code 方便对比学习
// 同时可以在Android studio中将java code转换为kotlin code
// 选择Java file 右键 convert java file to kotlin file
// 一时不知道kotlin的语法 可以先写java 再转为kotlin
// 甚至可以先写好Java 的代码 直接copy到Kotlin文件中
// Android Studio 会检测到剪切板是Java Code 询问你是否将Java代码转换为Kotlin代码
// 点击确认 可以直接转换
// kotlin程序的入口 与普通的Java文件不同 写在类外部
fun main() {
println("Hello World")
// Kotlin方法的学习
method();
}
fun method() {
println(sum(13, 14));
println(sum1(14, 14));
println(printSum(13,15))
println(printSum1(33,22))
}
// kotlin方法的定义
/*
方法关键字 方法名(参数1:参数1类型,参数2:参数2类型...):返回值类型{
方法体
}
*/
fun sum(a: Int, b: Int): Int {
println("start $a+$b")
return a + b
}
// 如果方法体内部只有一句话 可以简写成如下
// 返回类型可以推断 “=”类似"return"
fun sum1(a: Int, b: Int) = a + b
// 像sum方法内部有两行代码 无法缩写成sum1的样子
//fun sum2(a: Int, b: Int) = println("start $a+$b") a + b// 报错
// Unit 无意义的值 类似于 void
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
// Unit类型可以忽略不写
// 方法体内部的$a $b代表变量的实际值
// ${a + b} {}内部是一个表达式
// 如果返回值类型是Unit 还会打印kotlin.Unit的信息
fun printSum1(a: Int, b: Int) {
println("sum1 of $a and $b is ${a + b}")
}
class D01Start {
}
package com.example.lib.d01start
import java.lang.NumberFormatException
fun main() {
// 变量
variable()
// string 模板
stringTemplate()
// 条件表达式
condition()
// 空值检测
nullCheck()
// 类型检测与自动类型转换
typeCheck();
// 使用For循环
useFor();
// 使用while循环
useWhile();
// 使用when表达式
// TODO("学到了开始章节的when表达式 后面发现学习顺序不对 应该从基础一章开始学习")
val param = 1.2
useWhen(param)
}
// kotlin 版本的switch case
fun useWhen(obj: Any) {
when (obj) {
1 -> println("One")
"Hello" -> println("Greeting")
is Long -> println("Long")
!is String -> println("Not a string")
else -> println("Unknown")
}
}
fun useWhile() {
val items = listOf("apple", "banana", "kiwi")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
index = 0
while (index in items.indices) {
println("item at $index is ${items[index]}")
index++
}
}
fun useFor() {
// 增强for循环版本
for1()
// 角标访问版本
for2()
}
fun for1() {
// 类似于
// val items: List<String> = ArrayList(Arrays.asList("aaa", "bbb"))
val items = listOf("apple", "banana", "kiwi")
// kotlin中的遍历关键字in
// 这里省略了item的声明
for (item in items) {
println(item)
}
}
fun for2() {
val items = listOf("apple2", "banana2", "kiwi2")
// 类似于使用角标访问数组
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
//在使用is关键字内部 不需要再进行强制转换 在特定分支中 参数就是指定类型
fun typeCheck() {
// kotlin 可以在方法中定义方法
fun printLength1(obj: Any) {
// 打印某个对象的字符串长度
// ${getStringLength(obj) ?: "... err, not a string"} 花括号内是一个表达式
// ?: 看起来是java三元操作符的简写 ?:前面的如果不是空 直接使用这个值 否则使用?:后面的值
println(" $obj string length is ${getStringLength(obj) ?: "... err, not a string"} ")
}
printLength1("Incomprehensibilities")
printLength1(1000)
printLength1(listOf(Any()))
}
fun getStringLength(obj: Any): Int? {// Any代表任意类型
// is 相当于Java中的instanceof
if (obj is String) {
// `obj` 在该条件分支内自动转换成 `String`类型
return obj.length
} // 在离开类型检测分支后,`obj` 仍然是 `Any` 类型
return null
}
fun nullCheck() {
// 当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引?可为空
println("parseInt ==> " + stringToInteger("ww"))
println("parseInt ==> " + stringToInteger("12"))
printProduct("w", "2")
}
// 使用?表明 返回值可能为空
fun stringToInteger(s: String): Int? {
// 用到了Kotlin中使用try catch
return try {
Integer.valueOf(s)
} catch (e: NumberFormatException) {
null
}
}
fun printProduct(arg1: String, arg2: String) {
val x = stringToInteger(arg1)
val y = stringToInteger(arg2)
// 直接使? `x * y` 会导致编译错误, 因为它们可能为 null
if (x != null && y != null) {
// 在空检测后, x 与 y 会?动转换为?空值(non-nullable)
println(x * y)
} else {
println("'$arg1' or '$arg2' is not a number")
}
}
fun condition() {
println("max is :" + maxOf(2, 3))
println("max is :" + maxOf2(2, 3))
}
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
// 这里使用了第一节在函数时使用的简写
fun maxOf2(a: Int, b: Int) = if (a > b) a else b
// const 代表运行时常量
// 相当于 public static final double MY_CONSTANT
const val MY_CONSTANT = 3.1415
fun variable() {
// 变量声明的最常见方式
// 变量 变量名:变量类型 = 赋值
val a: Int = 1 // ?即赋值
// 省略变量类型的声明 可以通过自动推断推断出类型
val b = 2 // ?动推断出 `Int` 类型
val c: Int // 如果没有初始值类型不能省略
c = 3 // 明确赋值
println(c)
// 使用var来声明可变的变量
var x = "String"
println(x)
x = "new String"
println(x)
// 使用val来声明不可变的变量 val有点像final关键字 但不完全相等
val y = "String1111"
//y = "new String1"//报错 Val cannot be reassigned
// val 代表运行时常量
// 相当于 final double PI
val PI = 3.14
println(PI)
println(MY_CONSTANT)
}
fun stringTemplate() {
var a = 1
// $a代表打印变量中的真实的值
// 并且该次赋值以后 即使a的值变化了 s1的内容也不再变化
val s1 = "a is $a"
println(s1)
// 给变量a赋值新值2
a = 2
// 输出 now a is 2 and s1 is a is 1
println("now a is $a and s1 is $s1")
// ${}内部是一个表达式 调用了 String的replace方法
val s2 = "${s1.replace("is", "was")}, but now is $a"
// 输出 a was 1, but now is 2
println(s2)
}
class D02Start {
}
第二章 基础
知识点
章节:基本类型 包 控制流 返回与跳转
1. 基本类型?字面常量?显示转换?运算?数字比较?字符?布尔?数组 (?符号类型 跳过 因为他们似乎还不稳定)?string
2.as 关键字
3.if 表达式??when 表达式?for 循环遍历?while 循环
4.return?break continue的典型用法?学习使用标签?标签的隐式用法?返回标签时带有返回值
笔记
package com.example.lib.d02basic
/**
* 数据类型
* Java中char可以与数字进行比较 但是Kotlin中不行
* char a = 'a';
* if (a>10) System.out.println(a);
*
*
*/
// 十进制
const val NUMBER1 = 123
// 16进制的17
const val NUMBER2 = 0x11
// 2进制的5
const val NUMBER3 = 0b0101
// Kotlin 不支持八进制
fun main() {
// 基本类型
basicType()
// 字面常量
valVariable()
// 显示转换
explicitConvert()
// 运算
calculate()
// 数字比较
numberCompare()
// 字符
char()
// 布尔
bool();
// 数组
array()
// ?符号类型 跳过 因为他们似乎还不稳定
// String
string()
}
fun string() {
val string1: String = "This is String"
// 利用for循环 输出字符串
for (char in string1) {
println(char)
}
println(string1)
val s = "abc" + 1
// 字符串拼接
println(s + "def")
// 与上面等价
println("${s}def")
val i = 10
// 字符串模板
println("i = $i")
val s2 = "abc"
// ?花括号括起来的任意表达式(花括号内部是一个表达式)
println("$s2.length is ${s2.length}")
val beef = "beef"
val price = "99"
println("$beef is $$price")
}
fun array() {
val arrayOfInt: IntArray = intArrayOf(1, 3, 5, 7, 9)
// 创建?个 Array<String> 初始化为 ["0", "1", "3", "4", "5"]
val asc = Array(5) { element -> element }
// 利用数组自带的iterator遍历
asc.forEach { println(it) }
/**整型Int的数组*/
arrayOfInt.forEach { println(it) }
/**字符Char类型的数组*/
val arrayOfChar: CharArray = charArrayOf('H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd')
arrayOfChar.forEach { println(it) }
/**字符串String数组*/
val arrayOfString: Array<String> = arrayOf("Hello", "World")
for (element in arrayOfString) {
println(element)
}
// ??为 5、 值为 [0, 0, 0, 0, 0] 的整型数组
val arr1 = IntArray(5)
arr1.forEach { print("$it ") }
println()
// 例如: ?常量初始化数组中的值
// ??为 5、 值为 [42, 42, 42, 42, 42] 的整型数组
val arr2 = IntArray(5) { 42 }
arr2.forEach { print("$it ") }
println()
// 例如: 使? lambda 表达式初始化数组中的值
// ??为 5、 值为 [0, 1, 2, 3, 4] 的整型数组(值初始化为其索引值)
val arr3 = IntArray(5) { it * 1 }
arr3.forEach { print("$it ") }
println()
}
//三个引号"""括起来的字符串 内部没有转义并且可以包含换?以及任何其他字符
val definitionArray =
"""
public class Array<T> {
/**
* 数组的定义类 摘自Array.kt
*
*
* Creates a new array with the specified [size], where each element is calculated by calling the specified
* [init] function.
* 创建一个指定长度的新数组 每一个元素可以被指定的init方法计算
*
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an array element given its index.
* init方法被每一个元素从第一个元素开始依次调用 它应该返回元素下标的值
*/
public inline constructor(size: Int, init: (Int) -> T)
/**
* get方法 返回指定下标的元素
* Returns the array element at the specified [index]. This method can be called using the
* index operator.
* ```
* value = arr[index]
* ```
*
* If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS
* where the behavior is unspecified.
*/
public operator fun get(index: Int): T
/**
* set方法
* Sets the array element at the specified [index] to the specified [value]. This method can
* be called using the index operator.
* ```
* arr[index] = value
* ```
*
* If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS
* where the behavior is unspecified.
*/
public operator fun set(index: Int, value: T): Unit
/**
* 返回数组长度
* Returns the number of elements in the array.
*/
public val size: Int
/**
* 创建用于遍历数组的迭代器
* Creates an [Iterator] for iterating over the elements of the array.
*/
public operator fun iterator(): Iterator<T>
}
"""
fun bool() {
val a = true
val b = false
println(a || b)
println(a && b)
println(!a)
}
fun char() {
/*val a:Char = 'a'
if (a == 1){ //Operator '==' cannot be applied to 'Char' and 'Int'
}*/
val b: Char = '1'
println(b)
//\t转义制表符
//\b转义退格键
//\n转义换行
//\r转义回车符 不过没看懂效果。。
//\'转义单引号
//\"转义双引号
//\\转义斜杠
//\$转义美元符号
val c: String = "aa \t bb\b cc\n dddddd \r ee \' ff \" gg\\ hh\$ "
println(c)
val d: Char = '5'
println(decimalDigitValue(d))
val e: Char = 'e'
println(isSmallChar(e))
val f: Char = 'F'
println(isBigChar(f))
}
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9') {
throw IllegalArgumentException("Out of range")
}
return c.code - '0'.code // 利用数字在Unicode字符表里面的index位置 显式将char转换为数字
}
fun isSmallChar(c: Char): Boolean {
return c in 'a'..'z'
}
fun isBigChar(c: Char): Boolean {
return c in 'A'..'Z'
}
fun numberCompare() {
val a = 1.0
val b = 2.0
val c = 3.0
println(a == b)
println(a + b == c)
println(a != b)
println(a < b)
println(a > b)
println(a <= b)
println(a >= b)
// 上述几个比较操作符是所有数字类型通用的
val e = 5
println(e in 1..10)
println(e !in 1..10)
// in !in是区间判断符号 只能用在Int或者char数值上
}
fun calculate() {
val x = 5 / 2 // 与Java一样 整数相除还是整数 因此x是Int类型
// println(x == 2.5) Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2) // true
val y = 5L / 2 // Long 与 Int运算 得到Long类型
println(y == 2L)
val u = 5 / 2.0 // 自动推断类型为Double
println(u == 2.5)
val w = 5 / 2.toDouble() // 显示转换为Double
println(w == 2.5)
val v = 5 / 2f // 显示转换为float
println(v == 2.5f)
// 位运算 对1 有符号左移2位 与上16进制的
val b = 0b1100
println(b)
// 1 shl 2 = 0100
// 1100 & 0100 == 0100
val a = (1 shl 2) and b
println(a)
/**
其他位运算
shl(bits) – 有符号左移
shr(bits) – 有符号右移
ushr(bits) – ?符号右移
and(bits) – 位与
or(bits) – 位或
xor(bits) – 位异或
inv() – 位?
*/
}
fun explicitConvert() {
/*
val a: Int? = 1 // ?个装箱的 Int (java.lang.Integer)
val b: Long? = a // 编译出错 无法将Int的对象赋值给Long
val c: Long? = 1L // ?个装箱的 Long (java.lang.Long)
val d: Int? = c // 编译出错 无法将Long的对象赋值给Int
*/
/*
以下为Java代码
上面的Kotlin代码应该和当前的第一部分的Java Code类似
Integer a = 1; // ?个装箱的 Int (java.lang.Integer)
Long b = a; // 编译出错 无法将Int的对象赋值给Long
Long c= 1L; // ?个装箱的 Long (java.lang.Long)
Integer d= c; // 编译出错 无法将Long的对象赋值给Int
int a = 1; // ?个装箱的 Int (java.lang.Integer)
long b = a; // 可以编译
long c= 1L; // ?个装箱的 Long (java.lang.Long)
int d= c; // 编译出错 不能将long赋值给int
*/
val b: Byte = 1 // OK, 字?值是静态检测的
// val i: Int = b // 错误 较?的类型不能隐式转换为较?的类型
val i: Int = b.toInt() // OK: 显式拓宽
println(i)
/**
每个数字类型?持如下的转换:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
*/
// 虽然赋值和参数使用上没有隐式转换 但是算术运算会有重载做适当转换
val l = 1L + 3 // Long + Int => Long 不会出错
println(l)
}
fun valVariable() {
// 数字字?值中的下划线(? 1.1 起)
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
// 定义一个Int值 为100
val a: Int = -128
// 定义一个可空的Int值 将a赋值给它
val boxedA: Int? = a
// 定义另一个可空的Int值 将a赋值给它
val anotherBoxedA: Int? = a
// 定义一个Int值 为10000
val b: Int = 10000
// 定义一个可空的Int值 将b赋值给它
val boxedB: Int? = b
// 定义另一个可空的Int值 将b赋值给它
val anotherBoxedB: Int? = b
// 这里涉及Kotlin中的==和===的差别
// ==相当于java的equals
// ===相当于java的== 是地址比较
// 至于第一次输出是true 第二次是false 是因为Kotlin和Java一样 在内部保存了一些常量
// 如果新创建的Integer 属于区间[-128,127] 则会从常量池取出数据赋值
// 否则new一个新的Integer
// 具体可以参照https://blog.csdn.net/jdsjlzx/article/details/106350713
// 书里面的同?性应该指 地址比较相同
// 相等性指他们的equals方法返回的结果
println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
println(boxedA == anotherBoxedA) // true
println(boxedB == anotherBoxedB) // true
}
fun basicType() {
// 未超出 Int 最?值的整型值初始化的变量都会推断为 Int 类型
val one = 1 // Int
// 如果初始值超过了其最?值,那么推断为 Long 类型
val threeBillion = 3000000000 // Long
// 显式指定 Long 型值
val oneLong = 1L // Long
// 显式指定 Byte 型值
val oneByte: Byte = 1
// 以?数初始化的变量,编译器会推断为 Double 类型
val e = 2.7182818284 // Double
// 显式指定为 Float 类型
val eFloat = 2.7182818284f // Float
val eee = 2.7182818284f// 实际是Float 不会转换为double //Java中这么写 实际值是double类型 double myD = 2.7182818284f;
fun printDouble(d: Double) {
print(d)
}
// Kotlin 中的数字没有隐式拓宽转换
val i = 1 // Int 类型
val d = 1.1 // double 类型
val f = 1.1f // float 类型
printDouble(d)
// printDouble(i) // 错误: 类型不匹配
// printDouble(f) // 错误: 类型不匹配
}
class D02Basic01BasicType {
}
package com.example.lib.d02basic
// as 关键字
import java.io.File as MyFile // MyFile 代表“java.io.File”
fun main() {
val file = MyFile("filename")
// val pa = MyPattern()
val d03 = D02Basic02Package()
}
class D02Basic02Package {
}
package com.example.lib.d02basic
fun main() {
// if 表达式
conditionIf()
// when 表达式
conditionWhen()
// for 循环遍历
conditionFor()
// while 循环
conditionWhile()
}
fun conditionWhile() {
testWhile()
testDoWhile()
}
fun testDoWhile() {
var parameter = 5
do {
parameter--
println(parameter)
} while (parameter > 0)
}
fun testWhile() {
var parameter = 5
while (parameter > 0) {
parameter--
println(parameter)
}
}
fun conditionFor() {
val arrayOfString: Array<String> = arrayOf("Hello", "World","Kotlin")
// 经典for循环
classicTraverse(arrayOfString)
// iterator遍历
iteratorTraverse(arrayOfString)
val arrayOfInt: IntArray = intArrayOf(11, 14, 17)
// 区间表达式的for循环
intervalExpressionTraverse()
// 下标遍历
indexTraverse(arrayOfString)
// withIndex 遍历
withIndexTraverse(arrayOfString)
}
fun withIndexTraverse(arrayOfString: Array<String>) {
for ((index, value) in arrayOfString.withIndex()) {
println("the element at $index is $value")
}
}
fun indexTraverse(arrayOfString: Array<String>) {
for (i in arrayOfString.indices) {
println(arrayOfString[i])
}
}
fun intervalExpressionTraverse() {
// 输出1 2 3
for (element in 1..3) {
println(element)
}
// 从6 降序到0 步长2 输出6 4 2 0
for (i in 6 downTo 0 step 2) {
println(i)
}
}
fun iteratorTraverse(arrayOfString: Array<String>) {
val iterator = arrayOfString.iterator()
while (iterator.hasNext()){
println(iterator.next())
}
}
fun classicTraverse(arr: Array<String>) {
for (item in arr) {
println(item)
}
}
// when 语句相当于Java中的switch case
fun conditionWhen() {
// when 作为表达式使用
println(expression(2))
// when 作为表达式使用 所有分支已经覆盖可能结果
println(expression2(false))
// when 不作为作为表达式使用
sentence(2)
// when 表达式也可以将条件合并
multiCondition(1)
// 我们可以甚至可以用方法(?不只是常量)作为分?条件
println(expressionAsCondition("hello"))
println(expressionAsCondition("hello1"))
// 我们可以?任意表达式(?不只是常量)作为分?条件
expressionAsCondition2(11)
expressionAsCondition2(1)
// when里面的类型推断
println(hasPrefix(1))
println(hasPrefix("prefix"))
// when 表达式是bool值
boolWhen(1, 3)
}
fun boolWhen(x: Int, y: Int) {
when {
isEven(x) -> println("x is isEven")
isEven(y) -> println("y is isEven")
else -> println("x y are Odd.")
}
}
fun isEven(x: Int): Boolean {
return x % 2 == 0
}
// 判断字符串是否以prefix打头
// 将when表达式的值直接赋值给方法返回值
fun hasPrefix(x: Any): Boolean = when (x) {
// is String == true后 该分支里面 x是String类型的
is String -> x.startsWith("prefix")
else -> false
}
fun expressionAsCondition(x: String): String {
// 我们可以?任意表达式(甚至是方法作为分支条件 ?不只是常量)作为分?条件
val str: String = "test"
return when (x) {
getResString(str) -> "greeting"
else -> "none of the above"
}
}
fun getResString(param: String): String {
return if (param == "test") {
"hello"
} else {
"unknown"
}
}
val arrayOfInt: IntArray = intArrayOf(11, 14, 17)
fun expressionAsCondition2(x: Int) {
// 我们可以?任意表达式(?不只是常量)作为分?条件
when (x) {
in 1..10 -> print("x is in the range")
in arrayOfInt -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
}
fun parseInt(s: String): Int {
TODO("Not yet implemented")
}
fun multiCondition(x: Any) {
when (x) {
// when 表达式也可以将条件合并
0, 1 -> println("x == 0 or x == 1")
else -> println("otherwise")
}
}
fun sentence(obj: Any) {
// when 不作为作为表达式使用(不使用when的返回结果) 可以没有else分支
when (obj) {
1 -> println("x==1")
2 -> println("x==2")
}
}
fun expression(obj: Any): String {
// when 作为表达式使用(使用when的返回结果) 必须有else分支 除非所有分支已经覆盖可能结果
return when (obj) {
1 -> "x==1"
2 -> "x==2"
else -> { // 注意这个块
"unknown"
}
}
}
fun expression2(obj: Boolean): String {
// when 作为表达式使用(使用when的返回结果) 必须有else分支 除非所有分支已经覆盖可能结果
return when (obj) {
true -> "true..."
false -> "false..."
}
}
fun conditionIf() {
// 传统?法
val a = 10
val b = 12
var max1: Int = a
if (a < b) max1 = b
// With else
val max2: Int
if (a > b) {
max2 = a
} else {
max2 = b
}
// if本身是一个表达式 可以将他的结果传入参数
val max3 = if (a > b) {
println("Choose a")
a
} else {
println("Choose b")
b
}
// val max4 = if (condition) A else B
// 如果condition成立 max4 = A 否则 max4 = B
println(max3)
}
class D02Basic03Contrl {
}
package com.example.lib.d02basic
/**
* Kotlin 有三种结构化跳转表达式:
* return。默认从最直接包围它的函数或者匿名函数返回。
* break。终?最直接包围它的循环。
* continue。继续下?次最直接包围它的循环。
*/
fun main() {
// 测试return
testReturn(null)
testReturn("aa")
// break continue的典型用法
classicBreakContinue()
// 学习使用标签
testLabel()
// testLabel1 vs testLabel2 标签的意义
testLabel1()
testLabel2()
// 标签的隐式用法
testLabel3()
// testLabel3的另外一种写法
testLabel4()
// 模拟Break
mockBreak()
// 返回标签时带有返回值
println(returnLabel(listOf(1, 1, -1)))// 输出[]
println(returnLabel(listOf(1, 0, 1)))// 输出[number 1, zero, number 1]
}
/**
* 该方法用于理解
* 当要返?个回值的时候,解析器优先选?标签限制的 return,即
* return@a 1
* 意为“返回 1 到 @a ”,?不是“返回?个标签标注的表达式 (@a 1) ”。
*
* 传入的参数里面只要有-1 就会返回空list 有0的则返回结果 不会出现"number 0"而是出现"zero"
*/
fun returnLabel(ints: List<Int>): List<String> {
return ints.map label@{
if (it == 0) return@label "zero" // return at named label 返回到标签
if (it == -1) return emptyList() // return at returnLabel 返回整个方法
"number $it" // expression returned from lambda 返回的表达式
}
}
//foo(listOf(1, -1, 1)) // []
//foo(listOf(1, 0, 1)) // ["number 1", "zero", "number 1"]
fun mockBreak() {
// run:Calls the specified function block and returns its result.
// run:调用指定方法块并返回其结果
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // 从传? run 的 lambda 表达式?局部返回
// 意思应该是返回到run方法调用处而不是退出整个方法 关系到print(" done with nested loop")能否被调用
// 虽然break只能在循环中使用('break' and 'continue' are only allowed inside a loop) 在
// 普通的代码中 用return+label的方式可以模拟break的作用
println(it)
}
}
print(" done with nested loop")
}
fun testLabel1() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // ?局部直接返回到 foo() 的调?者 即跳出foo方法
println(it)
}
println("this point is unreachable")
}
fun testLabel2() {
listOf(1, 2, 3, 4, 5).forEach lit@{// 声明标签
if (it == 3) return@lit //使用标签 跳到声明标签的地方
// 局部返回到该 lambda 表达式的调?者, 即 forEach 循环 而不是跳出整个方法 其实类似一个continue
// 但是break和continue都是用在循环中的关键字 标签就起到替代作用
print(it)
}
println(" done with explicit label")
}
fun testLabel3() {
listOf(1, 2, 3, 4, 5).forEach {// 省略了标签的声明
if (it == 3) return@forEach // 局部返回到该 lambda 表达式的调?者, 即 forEach 循环
// 常情况下使?隐式标签更?便。本例就是一个隐式标签 该标签与接受该 lambda 的函数同名
print(it)
}
println(" done with implicit label")
}
fun testLabel4() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {// 这里使用了匿名内部类替代lambda表达式
// 因为return效果是推出函数执行体 那么这里的return只能跳出当前函数 起到的作用和上面一样 即一个continue
if (value == 3) return // 局部返回到匿名函数的调?者, 即 forEach 循环
print(value)
})
print(" done with anonymous function")
}
fun classicBreakContinue() {
for (i in 1..10) {
if (i == 3) {
continue // i 为 3 时跳过当前循环,继续下一次循环
}
println(i)
if (i > 5) {
break // i 为 6 时 跳出循环
}
}
}
fun testLabel() {
// 声明标签
loop@ for (i in 1..100) {
if (i == 10) break@loop //使用标签 跳到声明标签的地方 类似但不等价于C的goto
println(i)
}
}
fun testReturn(string: String?) {
println("start=====")
// ?:是一个二元表达式 如果 参数string==null 走前面的分支
// 否则 走后面的分支
val s = string ?: return
println(s)
println("end=====")
}
class D02Basic04BreakContinue {
}
|