Kotlin语法总结:Java代码文件转Kotlin代码文件改造注意细节
Posted LQS_Android
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin语法总结:Java代码文件转Kotlin代码文件改造注意细节相关的知识,希望对你有一定的参考价值。
我们可以通过androidStudio编辑器将Android的Java语言代码自动转化为Kotlin语言代码,但是这种转换是机械性的转换,没有体现出Kotlin语言简洁、高效的精髓,因此需要我们懂得Kotlin语法,对齐进行修改,已达到最优的高效代码:
下面将举几个简单的例子进行说明:
构造函数改造:
下面一个简单的数据Bean它有三个属性字段和2个构造函数,其中一个无参数的构造函数,另一个是多参数的构造函数,下面利用转化工具进行转化,结果如下:
package com.example.app.entity;
/**
* Copyright (c)2021 网络科技有限公司
*
* @author: LQS
* @date: 2021/8/16
* @description:
*/
class UserInfo {
private String name;
private String password;
private String code;
public UserInfo() {
}
public UserInfo(String name, String password, String code) {
this.name = name;
this.password = password;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
转化为Kotlin代码后,结果为:
/**
* Copyright (c)2021 网络科技有限公司
*
* @author: LQS
* @date: 2021/8/16
* @description:
*/
class UserInfo {
var name: String? = null
var password: String? = null
var code: String? = null
constructor() {}
constructor(name: String?, password: String?, code: String?) {
this.name = name
this.password = password
this.code = code
}
}
修改后的代码:
/**
* Copyright (c)2021 网络科技有限公司
*
* @author: LQS
* @date: 2021/8/16
* @description:
* ① 注意这里以多参数构造器为主构造器,构造器代码写到类名后面
* ② 以构造属性var声明三个字段,Kotlin会自动为三个属性字段name、password:、code生成getter()、setter()方法;
* ③ 单构造器放在类中,需要调用主构造器,参数不知道就传null;
*/
class UserInfo constructor(var name: String?, var password: String?, var code: String?) {
//注释见上
constructor():this(null,null,null) {}
}
数据类:关键字data
现实开发中的通常使用Model或者Bean作为数据的容器,它不仅需要实现拥有一些字段用于保存数据外,还需要实现一些常见的equals()、hashCode()、toString()、...等用于数据操作的方法。对于这样的数据容器类,在Kotlin语言中被统一定义为数据类,用在class前面加关键字data标识。
/**
* 添加关键字 data
**/
data class UserInfo constructor(var name: String?, var password: String?, var code: String?) {
//注释见上
constructor():this(null,null,null) {}
}
**
* Copyright (c)2021 网络科技有限公司
* @author: LQS
* @date: 2021/8/16
* @description:
*/
class Test {
private val user = UserInfo("AA","BB","CC");
/**
* UserInfo作为数据类型,默认自动实现copy()函数
*/
private val userCopy= user.copy();
fun main(){
println(user);
println(userCopy)
//在Kotlin当中运算符== 表示调用equals()函数
println(user==userCopy)
//在Kotlin当中运算符=== 表示地址比较,是否是同一个对象
println(user===userCopy)
}
}
在Java中需要使用【对象.字段属性】的方式获取值,而在Kotlin中,可以通过解构获取值:
解构形式:
再比如:
fun main(args: Array<String>) {
//创建User对象
val user1 = User("Tony", "123")
//解构
val(name1,pwd1) = user1
println(name1) //Tony
println(pwd1) //123
//省略解构password
val(name2, _) = user1
println(name2) //Tony
}
通过Elvis运算符进行优化:
when分支结构和表达式
when分支结构(when语句):
when (表达式) {
分支条件表达式1 -> {
语句组1
}
分支条件表达式2 -> {
语句组2
}
...
分支条件表达式n -> {
语句组n
}
else -> {
语句组n+1
}
}
when结构当做语句时,最后的else分支可以省略。另外,如果语句组所在的代码块只有一条语句,可以省略大括号。
val(或var) bar = when (表达式) {
分支条件表达式1 -> {
语句组1
表达式
}
分支条件表达式2 -> {
语句组2
表达式
}
...
分支条件表达式n -> {
语句组n
表达式
}
else -> {
语句组n+1
表达式
}
}
when表达式每一个分支最好是一条表达式,最后结束将表达式计算结果赋值给变量bar。需要注意的是when表达式不能省略else分支。
/**
* 静态内部类 internal修饰
*/
class LessonViewHolder internal constructor(itemView: View) : BaseViewHolder(itemView) {
internal fun onBind(lesson: Lesson) {
var date = lesson.date ?: "日期待定" //默认值
setText(R.id.tv_date, date)
setText(R.id.tv_content, lesson.content)
lesson.state?.let {
setText(R.id.tv_state, it.stateName())
/**
* when分支结构、表达式 是有返回值的
*/
val colorRes = when (it) {
Lesson.State.PLAYBACK -> R.color.playback
Lesson.State.LIVE -> R.color.live
Lesson.State.WAIT -> R.color.wait
}
val backgroundColor = itemView.context.getColor(colorRes)
getView<View>(R.id.tv_state)!!.setBackgroundColor(backgroundColor)
}
}
for循环语句
fun showPlayback() {
val playbackLessons: MutableList<Lesson> = ArrayList() //List初始化 不能修改
for (lesson in lessons) {
if (lesson.state=== Lesson.State.PLAYBACK) {
playbackLessons.add(lesson)
}
}
activity!!.showResult(playbackLessons)
}
使用forEach()函数、lambda表达式规则对上面的for()循环进行优化,先来看一些知识点补充:
关于forEach()函数补充:
forEach函数适用于Collection和Map集合,以及数组,函数只有一个函数类型的参数,实参往往使用尾随形式的Lambda表达式。在执行时forEach会把集合或数组中的每一个元素传递给Lambda表达式(或其他的函数引用)以便去执行:
public inline fun <T> Iterable<T>.forEach(action: (T) → Unit): Unit
fun main(args: Array<String>) {
val strArray = arrayOf("张三", "李四", "王五", "董六") //创建字符串数组
val set = setOf(1, 3, 34, 54, 75) //创建Set集合
val map = mapOf(102 to "张三", 105 to "李四", 109 to "王五") //创建Map集合
println("-----遍历数组-----")
strArray.forEach {
println(it)
}
println("-----遍历Set集合-----")
set.forEach {
println(it)
}
println("-----遍历Map集合k,v-----")
map.forEach { k, v -> ①
println("$k - $v")
}
println("-----遍历Map集合Entry-----")
map.forEach { ②
println("${it.key} - ${it.value}")
}
}
输出结果:
-----遍历数组集合-----
"张三"
"李四"
"王五"
"董六"
-----遍历Set集合-----
1
3
34
54
75
-----遍历Map集合k,v-----
102 - 张三
105 - 李四
109 - 王五
-----遍历Map集合Entry-----
102 - 张三
105 - 李四
109 - 王五
lambda表达式的使用补充:
{ 参数列表 ->
Lambda体
}
其中,Lambda表达式的参数列表与函数的参数列表形式类似,但是Lambda表达式参数列表前后没有小括号。箭头符号将参数列表与Lambda体分隔开,Lambda表达式不需要声明返回类型。Lambda表达式可以有返回值,如果没有return语句Lambda体的最后一个表达式就是Lambda表达式的返回值,如果有return语句返回值是return语句后面的表达式。
/**
* public inline fun <T> Iterable<T>.forEach(
* action: (T) → Unit
* ): Unit
*/
lessons.forEach({lesson->
if (lesson.state=== Lesson.State.PLAYBACK) {
playbackLessons.add(lesson)
}
})
根据②尾随lambda表达式规则可知,如上面代码所示的lambda表达式可以作为forEach(){}函数的参数传递,也可以写成尾随的形式,放到花括号{ }中:
lessons.forEach(){lesson->
if (lesson.state=== Lesson.State.PLAYBACK) {
playbackLessons.add(lesson)
}
}
根据③省略参数声明规则,如果Lambda表达式的参数只有一个,并且能够根据上下文环境推导出它的数据类型,那么这个参数声明可以省略,在Lambda体中使用隐式参数it替代Lambda表达式的参数,并且函数名后面的()可以省略:
lessons.forEach{it->
if (it.state=== Lesson.State.PLAYBACK) {
playbackLessons.add(it)
}
}
这时编译器会提示我们,如果lambda表达式的参数列表参数可用it代替,it可以省略,最后简化结果如下:
lessons.forEach {
if (it.state=== Lesson.State.PLAYBACK) {
playbackLessons.add(it)
}
}
public inline fun <T> kotlin.collections.Iterable<T>.filter(predicate: (T) -> kotlin.Boolean): kotlin.collections.List<T> {
/* compiled code */
}
data class User(val name: String, var password: String)
val users = listOf(
User("Tony", "12%^3"),
User("Tom", "23##4"),
User("Ben", "1332%#4"),
User("Alex", "ac133")
)
fun main(args: Array<String>) {
users.filter { it.name.startsWith("t", ignoreCase = true) }.forEach {println(it.password) }
}
输出结果:
12%^3
23##4
表达式it.name.startsWith("t", ignoreCase = true)是判断集合元素的name属性是否是t字母开头的,ignoreCase = true忽略大小写比较。filter函数处理完成之后的数据,由原来的四条数据编程了现在的两条数据。
forEach函数用来遍历集合元素,它的参数也是一个Lambda表达式,所以forEach {println(it.password) }是将集合元素的password属性打印输出。
map函数
public inline fun <T, R> kotlin.collections.Iterable<T>.map(transform: (T) -> R): kotlin.collections.List<R> { /* compiled code */ }
public inline fun <T, R> kotlin.collections.Iterable<T>.mapIndexed(transform: (kotlin.Int, T) -> R): kotlin.collections.List<R> { /* compiled code */ }
映射操作使用map函数,它可以对Collection集合、Map集合或数组元素进行变换返回一个List集合。
fun main(args: Array<String>) {
users.filter { it.name.startsWith("t", ignoreCase = true) } .map { it.name } .forEach{ println(it)}
}
聚合函数-归纳函数
聚合操作会将Collection集合或数组中数据聚合起来输出单个数据,聚合操作中最基础的是归纳函数reduce,reduce函数会将集合或数组的元素按照指定的算法积累叠加起来,最后输出一个数据。
data class Song(val title: String, val durationInSeconds: Int)
val songs= listOf(Song("Speak to Me", 90),
Song("Breathe", 163),
Song("On he Run", 216),
Song("Time", 421),
Song("The Great Gig in the Sky", 276),
Song("Money", 382),
Song("Us and Them", 462),
Song("Any Color You Like", 205),
Song("Brain Damage", 228),
Song("Eclipse", 123)
)
调用:
fun main(args: Array<String>) {
//计算所有歌曲播放时长之和
val durations = songs.map { it.durationInSeconds } .reduce { acc, i -> acc + i }
println(durations) //输出:2566
}
首先声明了一个数据类Song,它是保存Song对象的List集合。 调用map函数变换songs集合数据,返回歌曲时长(durationInSeconds)的List集合,再调用reduce函数计算时长,其中acc参数是上次累积计算结果,i当前元素,acc + i表达式是进行累加,这里表达式是关键,根据自己需要这表达式是不同的。
Kotlin语法糖规则、运算符、函数操作有很多,总结到此,起到抛砖引玉作用。
欢迎评论、关注!后续继续总结!
以上是关于Kotlin语法总结:Java代码文件转Kotlin代码文件改造注意细节的主要内容,如果未能解决你的问题,请参考以下文章