Kotlin是一种在Java虚拟机上运行的静态类型编程语言,被称之为Android世界的Swift,Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言,足见Kotlin将来会成为android开发的主流语言。
本文从Kotlin基础语法为入口,先了解一下Kotlin的基本数据类型,之后再阐述Kotlin中的运算符,最后在陈述一下Kotlin的条件控制及循环控制结构。本文只做Kotlin入门的参考资料,如有谬误、纰漏,望大家多多指教。
Kotlin中的基本数据类型包含:数值、字符、布尔、数组、字符串。
Kotlin数值类型包含Byte、Short,Int、Long、Float、Double等。不同于Java,字符不属于数值类型,是一个独立的数据类型。
类型 | 位宽度 |
Byte | 8 |
Short | 16 |
Int | 32 |
Long | 64 |
Float | 32 |
Double | 64 |
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ' 包含起来的。比如普通字符 '9','o'。如下写法是错误的:
fun check(c: Char) {
if (c == 1) { // 错误:类型不兼容
// ……
}
}
字符字面值用单引号括起来: '1'。 特殊字符可以用反斜杠转义。 支持这几个转义序列:\t、 \b、\n、\r、\'、\"、\\ 和 \$。 编码其他字符要用 Unicode 转义序列语法:'\uFF00'。我们可以显式把字符转换为 Int 数字:
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // 显式转换为数字
}
布尔用 Boolean 类型表示,它有两个值:true 和 false。内置的布尔运算有:
|| – 短路逻辑或 && – 短路逻辑与 ! - 逻辑非
数组用类 Array 实现,并且还有一个 size 属性及 get 和 set 方法,由于使用 [] 重载了 get 和 set 方法,所以我们可以通过下标很方便的获取或者设置数组对应位置的值。数组的创建两种方式:一种是使用函数arrayOf();另外一种是使用工厂函数。如下所示:
//[1,2,3]
val a = arrayOf(1, 2, 3)
//[0,2,4]
val b = Array(3, { i -> (i * 2) })
//读取数组内容
Log.d(TAG,a[0].toString()) // 输出结果:1
Log.d(TAG,b[1].toString()) // 输出结果:2
如上所述,[] 运算符代表调用成员函数 get() 和 set()。注意: 与 Java 不同的是,Kotlin 中数组是不协变的(invariant)。除了类Array,还有ByteArray, ShortArray, IntArray,用来表示各个类型的数组,省去了装箱操作,因此效率更高,其用法同Array一样:
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
和Java一样,String是不可变的。方括号[]语法可以很方便的获取字符串中的某个字符,也可以通过for循环来遍历:
for (c in str) {
Log.d(TAG,c.toString())
}
Kotlin支持三个引号"""扩起来的字符串,支持多行字符串,比如:
val text = """
多行字符串
多行字符串
"""
Log.d(TAG,text) // 输出有一些前置空格
字符串可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
var a = 1
// 模板中的简单名称:
val s1 = "a is $a"
a = 2
// 模板中的任意表达式:
val s2 = "${s1.replace("is", "was")}, but now is $a"
或者用花括号扩起来的任意表达式:
val s = "hello world"
val str = "$s.length is ${s.length}" // 求值结果为 "hello world.length is 11"
原生字符串和转义字符串内部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:
val price = "${'$'}9.99"
Log.d(TAG,price)
函数定义使用关键字fun,参数格式为:参数名: 类型,如:
fun sum(a: Int, b: Int): Int { // Int 参数,返回值 Int
return a + b
}
表达式作为函数体,返回类型自动推断:
fun sum(a: Int, b: Int) = a + b
public fun sum(a: Int, b: Int): Int = a + b // public 方法则必须明确写出返回类型
无返回值的函数(类似Java中的void) :
fun printSum(a: Int, b: Int): Unit {
Log.d(TAG,(a + b).toString())
}
// 如果是返回 Unit类型,则可以省略(对于public方法也是这样):
public fun printSum(a: Int, b: Int) {
Log.d(TAG,(a + b).toString())
}
函数的变长参数可以用vararg关键字进行标识:
fun vars(vararg v:Int){
for(vt in v){
Log.d(TAG,vt.toString())
}
}
lambda表达式使用实例:
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
变量定义使用var关键字,定义格式如下:
var <标识符> : <类型> = <初始化值>
变量定义使用val关键字,只能赋值一次的变量(类似Java中final修饰的变量),定义格式如下:
val <标识符> : <类型> = <初始化值>
常量与变量都可以没有初始化值,但是在引用前必须初始化,编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。
val a: Int = 1
val b = 1 // 系统自动推断变量类型为Int
val c: Int // 如果不在声明时初始化则必须提供变量类型
c = 1 // 明确赋值
var x = 5 // 系统自动推断变量类型为Int
x += 1 // 变量可修改
Kotlin 支持单行和多行注释,与 Java 不同的是,Kotlin 中的块注释允许嵌套。格式如下:
// 这是一个单行注释 /* 这是一个多行的 块注释。 */
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理。
//类型后面加?表示可为空
var age: String? = "23"
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1
当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null。 如:当 str 中的字符串内容不是一个整数时, 返回 null:
fun parseInt(str: String): Int? {
// ...
}
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。区间是为任何可比较类型定义的,但对于整型原生类型,它有一个优化的实现。以下是使用区间的一些示例:
for (i in 1..4) Log.d(TAG,i.toString()) // 输出“1234”
for (i in 4..1) Log.d(TAG,i.toString()) // 什么都不输出
if (i in 1..10) { // 等同于 1 <= i && i <= 10
Log.d(TAG,i.toString())
}
// 使用 step 指定步长
for (i in 1..4 step 2) Log.d(TAG,i.toString()) // 输出“13”
for (i in 4 downTo 1 step 2) Log.d(TAG,i.toString()) // 输出“42”
// 使用 until 函数排除结束元素
for (i in 1 until 10) { // i in [1, 10) 排除了 10
Log.d(TAG,i.toString())
}
作为一门计算机语言,运算符是必不可少的,Kotlin提供了一套丰富的运算符来操作变量,我们可以把运算符分成以下几类:
算术运算符用在数学表达式中,他们的作用和数学的作用一样。下表中列出了所有的算术运算符。
运算符 | 描述 |
+ | 加法-运算符两侧的值相加 |
- | 减法-左操作数减右操作数 |
* | 乘法-运算符两侧的值相乘 |
/ | 除法-左操作数除以右操作数,如果两个操作数为正数,为取商 |
% | 取余-做操作数除以做操作数的余数 |
++ | 自增-操作数的值增加1,对应方法为inc() |
-- | 自减-操作数的值减1,对应方法为dec() |
var a = 3
var b = 5
Log.d(TAG,"a = " + a +" b = " + b)
Log.d(TAG,"a + b = " + (a + b)) //加法
Log.d(TAG,"a - b = " + (a - b)) //减法
Log.d(TAG,"a * b = " + (a * b)) //减法
Log.d(TAG,"a / b = " + (a / b)) //减法
a++
Log.d(TAG,"a++" + a) //自增
b--
Log.d(TAG,"b--" + b) //自减
Kotlin中的关系运算符如下表所示:
运算符 | 描述 |
== | 检查两个操作数的值是否相等,如果相等则为真。相当于Java中的equals |
=== | 检查两个操作数的引用是否相等,如果相等则条件为真。相当于Java中的==。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 |
!== | 检查两个操作数的引用是否相等,如果不相等则条件为真。相等于Java中的!= |
> | 检查左操作数的值是否大于右操作数,如果是则条件为真。 |
< | 检查左操作数的值是否小于右操作数,如果是则条件为真。 |
>= | 检查左操作数的值是否大于或等于右操作数,如果是则为真。 |
<= | 检查左操作数的值是否小于或等于右操作数,如果是则为真。 |
var a = String("5".toByteArray())
var b = String("5".toByteArray()) //a、b为两个值相等的不同对象
var c = "5"
var d = "5"
Log.d(TAG,"a == b = " + (a == b))
Log.d(TAG,"a === b = " + (a === b))
Log.d(TAG,"c == d = " + (c == d))
Log.d(TAG,"c === d = " + (c === d))
Log.d(TAG,"a != b = " + (a != b))
Log.d(TAG,"a !== b = " + (a !== b))
Log.d(TAG,"c != d = " + (c != d))
Log.d(TAG,"c !== d = " + (c !== d))
Log.d(TAG,"a > b = " + (a > b))
Log.d(TAG,"a < b = " + (a < b))
Log.d(TAG,"a >= b = " + (a >= b))
Log.d(TAG,"a <= b = " + (a <= b))
对于Int和Long类型,还有一系列的位操作符可以使用,如下表所示:
符号或方法 | 说明 |
and 、and(bits) | 按位与 |
or 、or(bits) | 按位或 |
inv() | 按位非 |
xor 、xor(bits) | 按位异或 |
shl、shl(bits) | 左移运算符 |
shr、shr(bits) | 右移运算符 |
ushr、ushr(bits) | 无符号右移运算符 |
注意:and、or、xor、shl、shr、ushr即可以直接使用关键字,也可以调用对象的的方法。
var a = 0b001001
var b = 0b001001
var c = 0b001000
var d = -0b001000
Log.d(TAG,"a and b = " +a.and(b))
Log.d(TAG,"a and b = " +(a and b))
Log.d(TAG,"a and c = " +a.and(c))
Log.d(TAG,"a or c = " +a.or(c))
Log.d(TAG,"a or c = " +(a or c))
Log.d(TAG,"a inv = " +a.inv())
Log.d(TAG,"a xor c = " +a.xor(c))
Log.d(TAG,"a shl 2 = " +a.shl(2))
Log.d(TAG,"d shr 2 = " +d.shr(2))
Log.d(TAG,"d shr 2 = " +(d shr 2))
Log.d(TAG,"d ushr = " +d.ushr(2))
逻辑运算符有三种,下表列出所有的逻辑运算符:
操作符 | 描述 |
&& | 逻辑与。当且仅当两个操作数都为真,条件才为真。 |
|| | 逻辑或。如果两个操作数的任何一个为真,条件为真。 |
! | 逻辑非。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算将得到false。 |
Kotlin语音支持以下赋值符:
操作符 | 描述 |
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 |
+= | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 |
-= | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 |
*= | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 |
/= | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 |
%= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 |
我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做过类型判断以后,obj会被系统自动转换为String类型
return obj.length
}
// 这里的obj仍然是Any类型的引用
return null
}
或者
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
// 在这个分支中, `obj` 的类型会被自动转换为 `String`
return obj.length
}
甚至还可以
fun getStringLength(obj: Any): Int? {
// 在 `&&` 运算符的右侧, `obj` 的类型会被自动转换为 `String`
if (obj is String && obj.length > 0)
return obj.length
return null
}
和区间组合在一起,主要表示在…区间。如果要表示不再某一区间,可以使用!in。
可以用in判断数字是否在某个区间
// 检查x数值是否在1到4区间
if (x in 1..4){
}
可以用in判断集合中是否存在某个元素
// 检查list中是否有某个元素
if (name in list){
}
可以用in遍历整个区间或者集合
// 遍历
for(i in 1..4){
print(i) // 1234
}
// 设置步长
for(i in 1..4 step 2) {
print(i) // 13
}
// for(i in 4..1) // error
// 如果要从大到小遍历,可以使用downTo
for(i in 4 downTo 1 step 2) {
print(i) // 42
}
// until排除结束元素
for(i in 1 until 4) {
print(i) // 123
}
// 遍历list中的每个元素
for(item in list){}
该用法和Java一样,格式如下:
if(布尔表达式1){
...
}else if(布尔表达式2){
...
}
...
else if(布尔表达式n){
...
}
else{
...
}
实例代码如下:
var a = 5
var b = 6
// 传统用法
var max = a
if (a < b) max = b
// 使用 else
if (a > b) {
max = a
} else {
max = b
}
把要执行的IF语句块最后一句的值赋给一个变量,如果最后一条语句没有返回值,则返回为空。
var a = 5
var b = 6
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
使用in运算符来检测某个数字是否在指定区间内,区间格式为x..y。实例如下:
val x = 5
val y = 9
if (x in 1..8) {
println("x 在区间内")
}
when将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。when既可以被当做表达式使用也可以被当做语句使用。如果它被当做表达式,符合条件的分支的值就是整个表达式的值。如果当做语句使用,则忽略个别分支的值。when类似其他语言中的switch操作。其最简单的形式如下:
var a = 5
when (a) {
1 -> Log.d(TAG,"a == 1")
2 -> Log.d(TAG,"a == 2")
else -> { // 注意这个块
Log.d(TAG,"a 不是 1 ,也不是 2")
}
}
在when中,else同switch的default。如果其他分支都不满足条件将会求值else分支。如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分割:
var a = 5
when (a) {
0, 1 -> Log.d(TAG,"a == 0 or a == 1")
else -> Log.d(TAG,"otherwise")
}
我们也可以检测一个值在(in)或者不在(!in)一个区间或者集合中:
var a = 5
when (a) {
in 1..10 -> Log.d(TAG,"x is in the range")
!in 10..20 -> Log.d(TAG,"x is outside the range")
else -> Log.d(TAG,"none of the above")
}
我也可以用来检测一个值是(is)或者不是(!is)一个特定的类型的值。注意:由于智能转换,你可以访问该类型的方法和属性而无需 任何额外的检测。
fun hasPrefix(x:Any ){
when(x) {
is String -> x.startsWith("prefix")
else -> false
}
}
when也可以用来取代if-else if链。如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:
var a = 5
var b = 6
when {
a>b -> Log.d(TAG,"a > b")
else -> Log.d(TAG,"a < b")
}
when中也可以使用in运算符,用来判断集合内是否包含某实例:
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> Log.d(TAG,"juicy")
"apple" in items -> Log.d(TAG,"apple is fine too")
}
for循环可以对任何提供迭代器(iterator)的对象进行遍历,格式如下:
for(item in items) Log.d(TAG,item)
//或
for(item: Int in ints){
//...
}
如果你想要通过索引遍历一个数组或者一个list,你可以这样:
for (i in items.indices) {
Log.d(TAG,items[i])
}
这种“在区间上遍历”会编译成优化的实现而不会创建额外对象。或者你可以使用库函数withIndex:
for ((index, value) in items.withIndex()) {
Log.d(TAG,"the element at $index is $value")
}
val items = listOf("apple", "banana", "orange")
for (item in items) Log.d(TAG,item)
for (i in items.indices) {
Log.d(TAG,items[i])
}
for ((index, value) in items.withIndex()) {
Log.d(TAG,"the element at $index is $value")
}
while是最基本的循环,它的结构为:
while( 布尔表达式 ) {
//循环内容
}
对于while语句而言,如果不满足条件,则不能进入循环。但有的时候我们需要即使不满足条件,也至少执行一次,这是我们可以用 do...while。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do {
//代码语句
}while(布尔表达式);
Log.d(TAG,"----while 使用-----")
var x = 3
while (x > 0) {
Log.d(TAG, (x--).toString())
}
Log.d(TAG,"----do...while 使用-----")
var y = 5
do {
Log.d(TAG, (y--).toString())
} while(y>0)
Kotlin和其他语言一样,有三个结构化跳转关键字:return、break和continue,三种关键的作用如下:
在循环中,kotlin支持传统的break和continue操作符。
for (i in 0..9) {
if (i==3) continue // i 为 3 时跳过当前循环,继续下一次循环
Log.d(TAG,i.toString())
if (i>5) break // i 为 6 时 跳出循环
}
结果
在kotlin中任何表达式都可以用标签(label)来标记。标记的格式为标识符后面加@符号,如:loop@,abc@,都是有效标签。要为一个表达式加标签,我们只要在其前面加标签即可。
标签限制的break跳转到刚好位于该标签指定的循环后面的执行点,而continue标签指定的是循环下一次迭代。
实例如下:
//break标签
Log.d(TAG,"break start")
loop@ for (i in 1..5) {
for (j in 1..5) {
if (i > 2 && j > 3) break@loop
Log.d(TAG,"j = "+j)
}
Log.d(TAG,"i = "+i)
}
Log.d(TAG,"break end")
//continue标签
Log.d(TAG,"continue start")
loop@ for (i in 1..5) {
for (j in 1..5) {
if (i > 2 && j > 3) continue@loop
Log.d(TAG,"j = "+j)
}
Log.d(TAG,"i = "+i)
}
Log.d(TAG,"continue end")
运行结果如下:
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: break start
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 4
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 5
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: i = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 4
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 5
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: i = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: break end
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: continue start
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 4
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 5
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: i = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 4
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 5
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: i = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 1
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 2
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: j = 3
2021-12-09 16:47:37.152 5040-5040/com.panda.kotlintest D/MainActivity: continue end
Kotlin有函数字面量、局部函数和对象表达式,因此Kotlin的函数可以被嵌套。标签限制的return允许我们返回到外层函数。最重要的一个用途就是从lambda表达式中返回。回想一下我们这么写的时候:
fun foo() {
Log.d(TAG,"foo start")
var ints = listOf(1,2,3,0)
ints.forEach {
if (it == 0) return
Log.d(TAG,it.toString())
}
Log.d(TAG,"foo end")
}
这个 return 表达式从最直接包围它的函数即 foo 中返回。 (注意,这种非局部的返回只支持传给内联函数的 lambda 表达式。)
如果我们需要从 lambda 表达式中返回,我们必须给它加标签并用以限制 return。如下所示:
fun foo() {
Log.d(TAG,"foo start")
var ints = listOf(1,2,3,0)
ints.forEach lin@{
if (it == 0) return@lin
Log.d(TAG,it.toString())
}
Log.d(TAG,"foo end")
}
现在,它只会从 lambda 表达式中返回。通常情况下使用隐式标签更方便。 该标签与接受该 lambda 的函数同名。
fun foo() {
ints.forEach {
if (it == 0) return@forEach
Log.d(TAG,it.toString())
}
}
或者,我们用一个匿名函数替代 lambda 表达式。 匿名函数内部的 return 语句将从该匿名函数自身返回。
fun foo() {
var ints = listOf(1,2,3,0)
ints.forEach(fun(value: Int) {
if (value == 0) return
Log.d(TAG,value.toString())
})
}
当要返回一个值的时候,解析器优先选用标签限制的 return,代码如下:
var value =run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop it //
Log.d(TAG,"value = " +it)
}
}
Log.d(TAG,"return value = " +value)
意为"从标签 @loop 返回 it",而不是"返回一个标签标注的表达式 (@a it)"。