Kotlin学习(十五): 解构声明(Destructuring Declarations)
2017-11-03 08:26
465 查看
Kotlin1.1.3发布,Kotlin 插件现在支持在编辑器的提示中显示推导的变量、函数和参数类型。默认情况下该功能是禁用的,可以在编辑器的设置中启用它。
下面进入正文,有时候要获取一个对象的属性,会定义很多个变量,这样子就会很麻烦,而在Kotlin中有个很方便的用法,就是使用解构声明。
创建变量
在Java中创建多个变量Person person = new Person("person", 1); String name = person.getPerson(); int age = person.getAge();
而在Kotlin中创建变量的话是这样的
data class Person(val name: String, val age: Int) val person = Person("jowan", 1) var name = person.name var age = person.age
使用解构变量,同时创建多个变量
data class Person(val name: String, val age: Int) fun main(args: Array<String>) { val (name, age) = Person("person", 1) println(name) // 打印person println(age) // 打印1 }
这种语法就是解构声明,解构声明可以一次创建多个变量,通常用于数据类当中。
我们来看一下解构声明跟普通变量创建的区别:
编译后的代码:
在声明数据类的时候,会自动生成
componentN()方法,对应按声明顺序出现的所有属性,如
name就是
component1(),
age就是
component2(),而解构声明的
val (dName, dAge)事实上就是调用
component1()和
component2()方法。
循环
解构声明同样可以用在循环当中:data class Person(val name: String, val age: Int) val list: List<Person> = listOf(Person("one", 1), Person("two", 2), Person("three", 3), Person("four", 4)) fun main(args: Array<String>) { list.forEach { (name, age) -> println("name:$name, age:$age") } }
我们来看一下编译后的代码:
打印结果:
函数
解构声明也可以用在函数中,从函数中返回值:fun getPair(after: String?, afterAge: Int?): Pair<String, Int> { var name = "wangzai" var age = 23 // 处理返回的数据 name = after ?: name age = afterAge ?: age return Pair(name, age) } fun main(args: Array<String>) { val (name, age) = getPair("jowan", null) println("name:$name, age:$age") // 打印name:jowan, age:23 }
编译后的代码:
Map
解构声明还可以Map中,前提条件是:- 通过提供一个
iterator()函数将映射表示为一个值的序列
- 通过提供函数
component1()和
component2()来将每个元素呈现为一对
在Kotlin标准库里面自带有这样的扩展:
举个栗子:
val map: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3, "four" to 4) fun main(args: Array<String>) { map.forEach { (name, age) -> println("name:$name, age:$age") } }
编译后的代码:
下划线代替未使用变量(1.1版本)-Underscore for unused variables (since 1.1)
如果在解构声明中有用不到的变量,则可以使用下划线代替,如上面的栗子:fun getPair(): Pair<String, Int> { return Pair("one", 1) } fun main(args: Array<String>) { val (_, age) = getPair() println("age:$age") // 打印出age:1 }
来看看编译后的内容
可以看出没有声明使用下划线的变量。
在Lambda中的解构(1.1版本)-Destructuring in Lambdas (since 1.1)
如果Lambda具有Pair类型的参数(或
Map.Entry或具有相应
componentN函数的任何其他类型),则可以通过将它们放在括号中来引入几个新参数:
val map = mapOf(1 to 1, 2 to 2, 3 to 3) map.forEach { entry -> println("${entry.value}!") } map.forEach { a, b -> println("$a!$b!") }
注意声明参数和声明解构对之间的区别:
{ a -> ... }一个参数:
val map = mapOf(1 to 1, 2 to 2, 3 to 3) map.forEach { entry -> println("${entry.value}!") // 打印1!2!3! }
编译后的内容:
{ a, b -> ... }两个参数:
val map = mapOf(1 to 1, 2 to 2, 3 to 3) map.forEach { a, b -> println("$a!$b!") // 打印1!1!2!2!3!3! }
编译后的内容:
居然是这个样子的,我IDE是用IntelliJ IDEA的。
这时候怎么办呢?问了下大佬,大佬说可以换一种反编译的工具来看。。。
那么就换一种反编译的工具,在这里使用jd-gui来查看class文件里面的内容,打开jd-gui,然后把class文件拖进去就可以:
{ (a, b) -> ... }一个Pair类型的解构:
val map = mapOf(1 to 1, 2 to 2, 3 to 3) map.forEach { (_, value) -> println("$value!") // 打印1!2!3! }
编译后的内容:
这里可以看出解构对和两个参数的区别,解构对是通过调用iterator的,而两个参数则是通过调用
BiConsumer里面的
accept方法的。
{ (a, b), c -> ... }一个Pair类型的解构和一个参数:
val maps = mapOf((1 to 1) to 3, (2 to 2) to 2, (3 to 3) to 1) maps.forEach { (a, b), c -> println("$a!$b!$c") // 打印1!1!32!2!23!3!1 }
编译后的内容:
同样用jd-gui来看编译后的代码:
解构声明也可以指定解构的类型:
map.mapValues { (_, value) -> "$value!" } map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" } map.mapValues { (_, value: String) -> "$value!" }
相关文章推荐
- 学习kotlin第13天_具体化的类型参数、内联属性、解构声明、集合
- Kotlin学习笔记5-1 其他-解构声明
- Kotlin学习笔记(十)解构声明
- Kotlin解构声明和组件函数
- Destructuring Declarations in kotlin (kotlin的解构声明) 的正确打开方式
- Kotlin-解构声明
- Kotlin教程学习-函数定义,变量声明
- Kotlin学习之 4000 声明常量与变量
- Kotlin 学习(一)——对象的声明与创建
- Kotlin解构声明
- Kotlin-解构声明
- android kotlin其它(一)解构声明
- Kotlin学习(八): 对象表达式和声明(Object Expressions and Declarations)
- Kotlin语法(十五)-对象表达式和声明
- es6 学习笔记 之 变量声明 和 变量的 解构赋值
- Kotlin学习之-5.11 对象表达式和声明
- Kotlin学习之object表达式和声明
- Kotlin-25.解构声明(Destructuring Declaration)
- Kotlin教程学习-函数定义,变量声明
- Kotlin系列九----解构声明、集合