该如何高效实用Kotlin?,【金三银四】
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。贵在坚持!基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开
// 传统的做法
val age = -1;
if (age <= 0) {
throw IllegalArgumentException(“age must not be negative”)
}
// 使用 require 去检查
require(age > 0) { “age must be negative” }
// 使用 checkNotNull 检查
val name: String? = null
checkNotNull(name){
“name must not be null”
}
那么我们如何在项目中使用呢,具体的用法可以查看我 GitHub 上的项目 DataBindingDialog.kt 当中的用法。
4. 如何区分和使用 run, with, let, also, apply
run, with, let, also, apply 都是作用域函数,这些作用域函数如何使用,以及如何区分呢,我们将从以下三个方面来区分它们。
是否是扩展函数。
作用域函数的参数(this、it)。
作用域函数的返回值(调用本身、其他类型即最后一行)。
5. 是否是扩展函数
首先我们来看一下 with 和 T.run,这两个函数非常的相似,他们的区别在于 with 是个普通函数,T.run 是个扩展函数,来看一下下面的例子。
val name: String? = null
with(name){
val subName = name!!.substring(1,2)
}
// 使用之前可以检查它的可空性
name?.run { val subName = name.substring(1,2) }?:throw IllegalArgumentException(“name must not be null”)
在这个例子当中,name?.run 会更好一些,因为在使用之前可以检查它的可空性。
5.1 作用域函数的参数(this、it)
我们在来看一下 T.run 和 T.let,它们都是扩展函数,但是他们的参数不一样,T.run 的参数是 this, T.let 的参数是 it。
val name: String? = “hi-dhl.com”
// 参数是 this,可以省略不写
name?.run {
println(“The length is ${this.length} this 是可以省略的 ${length}”)
}
// 参数 it
name?.let {
println(“The length is ${it.length}”)
}
// 自定义参数名字
name?.let { str ->
println(“The length is ${str.length}”)
}
在上面的例子中看似 T.run 会更好,因为 this 可以省略,调用更加的简洁,但是 T.let 允许我们自定义参数名字,使可读性更强,如果倾向可读性可以选择 T.let。
5.2 作用域函数的返回值(调用本身、其他类型)
接下里我们来看一下 T.let 和 T.also 它们接受的参数都是 it, 但是它们的返回值是不同的,T.let 返回最后一行,T.also 返回调用本身。
var name = “hi-dhl”
// 返回调用本身
name = name.also {
val result = 1 * 1
“juejin”
}
println(“name = ${name}”) // name = hi-dhl
// 返回的最后一行
name = name.let {
val result = 1 * 1
“hi-dhl.com”
}
println(“name = ${name}”) // name = hi-dhl.com
从上面的例子来看 T.also 似乎没有什么意义,细想一下其实是非常有意义的,在使用之前可以进行自我操作,结合其他的函数,功能会更强大。
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }
当然 T.also 还可以做其他事情,比如利用 T.also 在使用之前可以进行自我操作特点,可以实现一行代码交换两个变量,在后面会有详细介绍
5.3 T.apply 函数
通过上面三个方面,大致了解函数的行为,接下来看一下 T.apply 函数,T.apply 函数是一个扩展函数,返回值是它本身,并且接受的参数是 this。
// 普通方法
fun createInstance(args: Bundle) : MyFragment {
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
// 改进方法
fun createInstance(args: Bundle)
= MyFragment().apply { arguments = args }
// 普通方法
fun createIntent(intentData: String, intentAction: String): Intent {
val intent = Intent()
intent.action = intentAction
intent.data=Uri.parse(intentData)
return intent
}
// 改进方法,链式调用
fun createIntent(intentData: String, intentAction: String) =
Intent().apply { action = intentAction }
.apply { data = Uri.parse(intentData) }
汇总
以表格的形式汇总,更方便去理解
函数 是否是扩展函数 函数参数(this、it) 返回值(调用本身、最后一行)
with 不是 this 最后一行
T.run 是 this 最后一行
T.let 是 it 最后一行
T.also 是 it 调用本身
T.apply 是 this 调用本身
6. 使用 T.also 函数交换两个变量
接下来演示的是使用 T.also 函数,实现一行代码交换两个变量?我们先来回顾一下 Java 的做法。
int a = 1;
int b = 2;
// Java - 中间变量
int temp = a;
a = b;
b = temp;
System.out.println("a = “+a +” b = "+b); // a = 2 b = 1
// Java - 加减运算
a = a + b;
b = a - b;
a = a - b;
System.out.println("a = " + a + " b = " + b); // a = 2 b = 1
// Java - 位运算
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a = " + a + " b = " + b); // a = 2 b = 1
// Kotlin
a = b.also { b = a }
println(“a = ${a} b = ${b}”) // a = 2 b = 1
来一起分析 T.also 是如何做到的,其实这里用到了 T.also 函数的两个特点。
调用 T.also 函数返回的是调用者本身。
在使用之前可以进行自我操作。
也就是说 b.also { b = a } 会先将 a 的值 (1) 赋值给 b,此时 b 的值为 1,然后将 b 原始的值(2)赋值给 a,此时 a 的值为 2,实现交换两个变量的目的。
7. in 和 when 关键字
使用 in 和 when 关键字结合正则表达式,验证用户的输入,这是一个很酷的技巧。
// 使用扩展函数重写 contains 操作符
operator fun Regex.contains(text: CharSequence) : Boolean {
return this.containsMatchIn(text)
}
// 结合着 in 和 when 一起使用
when (input) {
in Regex(“[0–9]”) -> println(“contains a number”)
in Regex(“[a-zA-Z]”) -> println(“contains a letter”)
}
in 关键字其实是 contains 操作符的简写,它不是一个接口,也不是一个类型,仅仅是一个操作符,也就是说任意一个类只要重写了 contains 操作符,都可以使用 in 关键字,如果我们想要在自定义类型中检查一个值是否在列表中,只需要重写 contains() 方法即可,Collections 集合也重写了 contains 操作符。
val input = “kotlin”
when (input) {
in listOf(“java”, “kotlin”) -> println(“found ${input}”)
in setOf(“python”, “c++”) -> println(“found ${input}”)
else -> println(" not found ${input}")
}
8. Kotlin 的单例三种写法
我汇总了一下目前 Kotlin 单例总共有三种写法:
使用 Object 实现单例。
使用 by lazy 实现单例。
可接受参数的单例(来自大神 Christophe Beyls)。
8.1 使用 Object 实现单例
代码:
object WorkSingleton
Kotlin 当中 Object 关键字就是一个单例,比 Java 的一坨代码看起来舒服了很多,来看一下编译后的 Java 文件。
public final class WorkSingleton {
public static final WorkSingleton INSTANCE;
static {
WorkSingleton var0 = new WorkSingleton();
INSTANCE = var0;
}
}
通过 static 代码块实现的单例,优点:饿汉式且是线程安全的,缺点:类加载时就初始化,浪费内存。
8.2 使用 by lazy 实现单例
利用伴生对象 和 by lazy 也可以实现单例,代码如下所示。
class WorkSingleton private constructor() {
companion object {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
总结
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。


然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-NyRKapeV-1712035752325)]
总结
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
[外链图片转存中…(img-gPP4NJqs-1712035752326)]
[外链图片转存中…(img-A0Hb6bWp-1712035752326)]
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
更多推荐



所有评论(0)