//Do not
fun dumpBook(book: Book?) {
if (book != null) {
book.dumpContent()
}
}
//Do
fun dumpBook1(book: Book?) {
book?.dumpContent()
}
进行类型转换并访问一些属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// avoid if type checks
//Do not
fun testTypeCheck(any: Any) {
if (any is Book) {
println(any.isbn)
}
}
//Do
fun testTypeCheck0(any: Any) {
(any as? Book)?.let {
println(it.isbn)
}
}
避免使用!!非空断言
1
2
3
4
5
6
7
8
9
//Do not
fun testNotNullAssertion(feed: Feed) {
feed.feedItemList.first().author!!.title
}
//Do
fun testNotNullAssertion0(feed: Feed) {
feed.feedItemList.first().author?.title ?: "fallback_author_title"
}
补充:
使用!!断言,一旦断言条件出错,会发生运行时异常。
判断可能为null的boolean值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Do not
fun comsumeNullableBoolean() {
var isOK: Boolean? = null
if (isOK != null && isOK) {
//do something
}
}
//Do
fun comsumeNullableBoolean0() {
var isOK: Boolean? = null
if (isOK == true) {
//do something
}
}
class Navigator {
fun turnLeft() = Unit
fun turnRight() = Unit
fun forward() = Unit
fun backward() = Unit
}
//use with
//Do not
fun navigate(navigator: Navigator) {
navigator.forward()
navigator.turnRight()
navigator.backward()
navigator.turnLeft()
}
//Do
fun navigate1(navigator: Navigator) {
with(navigator) {
forward()
turnRight()
backward()
turnLeft()
}
}
直接使用top-level方法,而不是Object里的方法
1
2
3
4
5
6
7
8
9
10
11
12
//Do not
object AppUtil {
fun isAppEnabled(packageName: String): Boolean {
TODO()
}
}
//Do
//AppUtil.kt file
fun isAppEnabled(packageName: String): Boolean {
TODO()
}
//Do not
fun isStringPhoneNumber(value: String): Boolean {
TODO()
}
//Do
fun String.isPhoneNumber(): Boolean = TODO()
使用方法引用
1
2
3
4
5
6
7
8
9
10
11
//Do not
data class NewsItem(val content: String, val isFake: Boolean)
fun normalLambda() {
arrayOf<NewsItem>().filter { it.isFake }.let { print(it) }
}
fun methodReference() {
arrayOf<NewsItem>().filter(NewsItem::isFake).let(::print)
}
//Do not
fun delayTask(task: () -> Unit, delayInMillSecond: Long) {
TODO()
}
//Do
fun delayTask0(delayInMillSecond: Long, task: () -> Unit) {
TODO()
}
fun testDelayTasks() {
delayTask({
println("printing")
}, 5000L)
delayTask0(5000L) {
println("printing")
}
}
使用mapNotNull
1
2
3
4
5
6
7
8
9
//Do not
fun testMapNotNull(list: List<FeedItem>) {
list.map { it.author }.filterNotNull()
}
//Do
fun testMapNotNull0(list: List<FeedItem>) {
list.mapNotNull { it.author }
}
尽可能使用只读集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun parseArguments(arguments: Map<String, String>) {
//do some bad things
//try to clear if the argument is available to be cleared.
(arguments as? HashMap)?.clear()
}
//use read-only collections as much as possible
//Do not
fun useMutableCollections() {
val arguments = hashMapOf<String, String>()
arguments["key"] = "value"
parseArguments(arguments)
}
//Do
fun useReadOnlyCollections() {
val arguments = mapOf("key" to "value")
parseArguments(arguments)
}
适宜情况下使用Pair或Triple
1
2
3
4
5
6
7
8
// Use Pair or Triple
fun returnValues(): Pair<Int, String> {
return Pair(404, "File Not Found")
}
fun returnTriple(): Triple<String, String, String> {
return Triple("6时", "6分", "60秒")
}
//Do not
class Car {
private var engine: String? = null
constructor(theEngine: String) {
engine = theEngine
}
constructor(car: Car) {
engine = car.engine
}
}
//Do
data class Car0(val engine: String)
fun test() {
val firstCar = Car("Honda")
val secondCar = Car(firstCar)
val thirdCar = Car0("Nissan")
val fourthCar = thirdCar.copy()
val fifthCar = thirdCar.copy(engine = "Ford")
}
针对函数类型和集合使用typealias
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Do not
interface OnValueChangedListener {
fun onValueChanged(value: String)
}
//Do
typealias OnValueChangedListener0 = (String) -> Unit
val value : OnValueChangedListener0 = {
println(it)
}
//Do
typealias BookSet = HashSet<Book>
val bookSet = BookSet().apply {
add(Book("978-0131872486"))
}
使用含义更加清晰的substringBefore和substringAfter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Do not
fun testSubstring() {
val message = "user|password"
Log.i("testSubstring.user=", message.substring(0, message.indexOf("|")))
Log.i("testSubstring.password=", message.substring(message.indexOf("|") + 1))
}
fun testSubstring0() {
val message = "user|password"
Log.i("testSubstring.user=", message.substringBefore("|"))
Log.i("testSubstring.password=", message.substringAfter("|"))
}