最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • let、run、with、apply 以及 also 这5种作用域函数各自的角色定位;

  • 5种作用域函数的差异区分;

  • 何时何地使用这5种作用域?

Kotlin的作用域函数


Kotlin 标准库包含几个函数,它们的唯一目的是在对象的上下文中执行代码块。当对一个对象调用这样的函数并提供一个 lambda 表达式时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。这些函数称为作用域函数。

简单来说,作用域函数是为了方便对一个对象进行访问和操作,你可以对它进行空检查或者修改它的属性或者直接返回它的值等操作,下面提供了案例对作用域函数进行了详细说明。

角色定位


2.1 let

public inline fun <T, R> T.let(block: (T) -> R): R

let函数是参数化类型 T 的扩展函数。在let块内可以通过 it 指代该对象。返回值为let块的最后一行或指定return表达式。

我们以一个Book对象为例,类中包含Book的name和price,如下:

class Book() {

var name = “《数据结构》”

var price = 60

fun displayInfo() = print(“Book name : $name and price : $price”)

}

fun main(args: Array) {

val book = Book().let {

it.name = “《计算机网络》”

“This book is ${it.name}”

}

print(book)

}

控制台输出:

This book is 《计算机网络》

在上面案例中,我们对Book对象使用let作用域函数,在函数块的最后一句添加了一行字符串代码,并且对Book对象进行打印,我们可以看到最后控制台输出的结果为字符串“This book is 《计算机网络》”。

按照我们的编程思想,打印一个对象,输出必定是对象,但是使用let函数后,输出为最后一句字符串。这是由于let函数的特性导致。因为在Kotlin中,如果let块中的最后一条语句是非赋值语句,则默认情况下它是返回语句。

那如果我们将let块中最后一条语句修改为赋值语句,会发生什么变化?

fun main(args: Array) {

val book = Book().let {

it.name = “《计算机网络》”

}

print(book)

}

控制台输出:

kotlin.Unit

可以看到我们将Book对象的name值进行了赋值操作,同样对Book对象进行打印,但是最后控制台的输出结果为“kotlin.Unit”,这是因为在let函数块的最后一句是赋值语句,print则将其当做是一个函数来看待。

这是let角色设定的第一点:1️⃣

  • let块中的最后一条语句如果是非赋值语句,则默认情况下它是返回语句,反之,则返回的是一个 Unit类型

我们来看let第二点:2️⃣

  • let可用于空安全检查。

如需对非空对象执行操作,可对其使用安全调用操作符 ?. 并调用 let 在 lambda 表达式中执行操作。如下案例:

var name: String? = null

fun main(args: Array) {

val nameLength = name?.let {

it.length

} ?: “name为空时的值”

print(nameLength)

}

我们设置name为一个可空字符串,利用name?.let来进行空判断,只有当name不为空时,逻辑才能走进let函数块中。在这里,我们可能还看不出来let空判断的优势,但是当你有大量name的属性需要编写的时候,就能发现let的快速和简洁。

let第三点:3️⃣

  • let可对调用链的结果进行操作。

关于这一点,官方教程给出了一个案例,在这里就直接使用:

fun main(args: Array) {

val numbers = mutableListOf(“One”,“Two”,“Three”,“Four”,“Five”)

val resultsList = numbers.map { it.length }.filter { it > 3 }

print(resultsList)

}

我们的目的是获取数组列表中长度大于3的值。因为我们必须打印结果,所以我们将结果存储在一个单独的变量中,然后打印它。但是使用“let”操作符,我们可以将代码修改为:

fun main(args: Array) {

val numbers = mutableListOf(“One”,“Two”,“Three”,“Four”,“Five”)

numbers.map { it.length }.filter { it > 3 }.let {

print(it)

}

}

使用let后可以直接对数组列表中长度大于3的值进行打印,去掉了变量赋值这一步。

另外,let函数还存在一个特点。

let第四点:4️⃣

  • let可以将“It”重命名为一个可读的lambda参数。

let是通过使用“It”关键字来引用对象的上下文,因此,这个“It”可以被重命名为一个可读的lambda参数,如下将it重命名为book

fun main(args: Array) {

val book = Book().let {book ->

book.name = “《计算机网络》”

}

print(book)

}

2.2 run

run函数以“this”作为上下文对象,且它的调用方式与let一致。

另外,第一点:1️⃣** 当 lambda 表达式同时包含对象初始化和返回值的计算时,run更适合。**

这句话是什么意思?我们还是用案例来说话:

fun main(args: Array) {

Book().run {

name = “《计算机网络》”

price = 30

displayInfo()

}

}

控制台输出:

Book name : 《计算机网络》 and price : 30

如果不使用run函数,相同功能下代码会怎样?来看一看:

fun main(args: Array) {

val book = Book()

book.name = “《计算机网络》”

book.price = 30

book.displayInfo()

}

控制台输出:

Book name : 《计算机网络》 and price : 30

输出结果还是一样,但是run函数所带来的代码简洁程度已经显而易见。

除此之外,让我们来看看run函数的其他优点:

通过查看源码,了解到run函数存在两种声明方式

1、与let一样,run是作为T的扩展函数;

inline fun <T, R> T.run(block: T.() -> R): R

2、第二个run的声明方式则不同,它不是扩展函数,并且块中也没有输入值,因此,它不是用于传递对象并更改属性的类型,而是可以使你在需要表达式的地方就可以执行一个语句。

inline fun run(block: () -> R): R

如下利用run函数块执行方法,而不是作为一个扩展函数:

run {

val book = Book()

book.name = “《计算机网络》”

book.price = 30

book.displayInfo()

}

2.3 with

inline fun <T, R> with(receiver: T, block: T.() -> R): R

with属于非扩展函数,直接输入一个对象receiver,当输入receiver后,便可以更改receiver的属性,同时,它也与run做着同样的事情。

还是提供一个案例说明:

fun main(args: Array) {

val book = Book()

with(book) {

name = “《计算机网络》”

price = 40

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题全套解析,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。

image

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

司2019-2021年的高频面试题全套解析,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。

[外链图片转存中…(img-JSFuiEov-1714834867387)]

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-C08Weorn-1714834867388)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐