Kotlin — 最佳实践
使用表达式
不建议:
fun getDefaultSex(name:String):User{ if(name=="mike"||name=="jack"){ return male; } if(name="marry"||name="jane"){ return female } return male }
建议:
fun getDefaultSex(name:String)=when(name){ "mike","jack"->male "marry","jane"->female else->male }
每次使用if的时候都考虑一下,表达式是否可以用更简洁的方式代替。
try-catch也是一个表达式:
var string="" string=try{ return "Ok" }catch(e:Exception){ return "Error" }
扩展函数
在Java中,我们经常在Util类中创建静态Util方法。这种模式翻译成Kotlin将如下所示:
不建议:
object StringUtils{ fun countNum(num:Int):Int{ return num*2 } } StringUtils.countNum(3)
Kotlin允许移除不必要的包装类,并使用扩展函数。通常我们还可以利用扩展函数来挺高可读性。
建议:
fun Int.countNum():Int{ return plus(2) } 3.countNum()
输出结果:
5
变量名代替Setter
在Java中,我们常为变量添加getter/setter方法,这样就会有大量的模板代码。
不建议:
val params=User() .setName("android coder") .setAge(25) .setSex("male")
在Kotlin中,命名和默认参数可以直接赋值:
建议:
val params=User(name="android coder",age=25,sex="male")
apply()为Grouping Object初始化
不建议:
val user=User() user.Name="android code" user.age=25 user.sex=male user.isDream=true
扩展函数apply()可以对对象的初始化代码进行分组和集中。这样,我们就不必一遍一遍的重复变量名称了。
建议:
val user=User().apply{ name="android coder" age=25 sex="male" isDream=true }
当处理Java类时apply()往往会很有用
不要重载默认构造函数
不要重载方法和构造函数来实现默认参数
不建议:
fun user(name:String){ user(name,true) } fun find(name:String,isDream:Boolean){ }
建议:
fun user(name:String,isDream:Boolean=true){ }
事实上,默认参数几乎取代了方法和构造函数重载的写法,因为,重载主要用于创建默认函数。
清晰简单处理NULL
避免if-null检查
不建议:
if(user==null||user.name==null||user.age==null){ throw IllegalArgumentException("Invalid User") } val name=user.name
每次我们都要写一个if-null检查。Kotlin提供了更好的方法来处理空值。使用as?和?:来检查类型,如果不是我们需要的,则抛出一个异常
建议:
user as? VIPUser ?:throw IllegalArgumentException("NO VIP") user.getVIP()
避免not-null断言!!
不建议:
user!!.vip!!.name!!.address!!
双重感叹号看起来会让你很烦。这是故意这么设计的,Kotlin的设计者正试着让你朝着一个更好的方向发展,而这个解决方案并不涉及编译器无法验证的断言。来源于:“Kotlin in Action”—>Dmitry Jemerov和Svetlana Isakova。
考虑使用let()
有时候,let()可以是if的简洁版。但是,你必须以合理的方式来使用它,以免出现问题。
val user:User?=findUser() if(user!=null){ println(user.name) }
当使用let()时,不需要额外的变量
class findUser{ val name:String=" } findUser()?.let{println(it.name)} //或者 findUser()?.customer?.let(::print)
简单的单表达函数映射
不建议:
fun mapToDTO(entity: SnippetEntity): SnippetDTO { val dto = SnippetDTO( code = entity.code, date = entity.date, author = "${entity.author.firstName} ${entity.author.lastName}" ) return dto }
使用单个表达式函数和命名参数,我们可以在对象之间编写简单,简洁和可读的映射。
建议:
fun mapToDTO(entity: SnippetEntity) = SnippetDTO( code = entity.code, date = entity.date, author = "${entity.author.firstName} ${entity.author.lastName}" ) val dto = mapToDTO(entity)
如果你对扩展功能熟悉,你可以在这里使用它们来使函数定义和使用更短,更易读。同时,我们不会用映射逻辑来破坏value对象
fun SnippetEntity.toDTO() = SnippetDTO( code = code, date = date, author = "${author.firstName} ${author.lastName}" ) val dto = entity.toDTO()
在Property Initializers时参考构造函数参数
不建议:
class UsersClient(baseUrl: String, appName: String) { private val usersUrl: String private val httpClient: HttpClient init { usersUrl = "$baseUrl/users" val builder = HttpClientBuilder.create() builder.setUserAgent(appName) builder.setConnectionTimeToLive(10, TimeUnit.SECONDS) httpClient = builder.build() } fun getUsers(){ //call service using httpClient and usersUrl } }
我们可以在属性初始化时引用主构造函数(而不是在init块中)。apply()可以帮助初始化代码分组。
class UsersClient(baseUrl: String, appName: String) { private val usersUrl = "$baseUrl/users" private val httpClient = HttpClientBuilder.create().apply { setUserAgent(appName) setConnectionTimeToLive(10, TimeUnit.SECONDS) }.build() fun getUsers(){ //call service using httpClient and usersUrl } }
解构
一方面,解构对于从一个函数返回多个值是很有用的。我们可以定义一个自己的数据类,或者使用Pair。
data class User(name:String,age:Int) fun createUser:User{ return User("android coder",25) } //使用解构 val (name,age)=createUser()
另一方面,解构可以用于map映射
val map=mapOf("android coder" to name,25 to age) for((name,age) in map){ //do something }
创建特殊的结构
listOf、mapOf、和infix函数可以用来创建JSON。
val user=mapOf( "name" to "android coder", "age" to 25, "language" to listOf("chinese","english") "address" to mapOf( "city" to "china" "pronvice" to "beijing" "street" to "chaoyang" ) )
通常我们应该使用数据类和对象映射来创建JSON。但有时(例如在测试中)这是非常有用的。
原文地址:https://www.jianshu.com/p/b9cba3aa8f8a
相关推荐
-
原创|ES广告倒排索引架构演进与优化 Java基础
2020-6-15
-
使用p6spy格式化日志输出 Java基础
2019-10-11
-
Java高性能高并发秒杀系统设计与优化 Java基础
2019-8-22
-
Java AQS无码讲解 Java基础
2019-3-4
-
解决方案:如何防止数据重复插入? Java基础
2019-9-16
-
搞定所有的跨域请求问题: jsonp & CORS Java基础
2018-3-18
-
Kafka连接器深度解读之JDBC源连接器 Java基础
2020-5-28
-
高可用的一些思考和理解 Java基础
2019-10-3
-
通过代码实例说明如何化腐朽为优雅 Java基础
2019-5-13
-
Electron,从玩玩具的心态开始,到打造出一款越来越优秀的桌面客户端产品 —— 一份不是「Hello Word」的吊胃口的Quick Start Java基础
2020-5-29