annotation class AnnoX(val value: String)
annotation class AnnoY(
val message: String
val annoX: AnnoX = AnnoX(“X”))
2.3 处理注解
如果没有相应的注解信息处理逻辑流程,那么注解可以说是废了,没有什么实用价值。
首先,我们的目标测试类是:
@Run
class SwordTest() {
@TestCase(id = “a”)
fun testCase(testId: String) {
println(“Run SwordTest Id = $testId”)
}
}
我们需要在 @TestCase注解作用在函数上的处理过程
::class
引用
首先声明一个变量指向SwordTest实例
然后就可以通过这个变量来获取该对象的类的信息,使用 ::class
来获取 sword对象实例的 KClass类的引用
val sword = SwordTest()
val kClass = sword::class
//有点像Java中的 getClass()
//上面这行代码,Kotlin编译器会自动推断出 kClass变量的类型是
val kClass:KClass = sword::class
- members扩展属性
下面我们需要获取 sword对象类型所声明的所有函数。Kotlin中 可以直接使用扩展属性 declaredFunctions来获取这个类中声明的所有函数。
//返回的是一个 Collection<KCallable<>> 其中是Koltlin泛型中的星投影
val members = kClass.members
- annotations属性
KFunction 类型继承了 KCallable,KCallable又继承了 KAnnotatedElement。KAnnotatedElement中有个public val annotations:List
属性里存储了该函数所有的注解信息。通过遍历这个存储Annotation的List,可以获取到TestCase注解:
for (f in members ) {
f.annotations.forEach {
if(it is TestCase){
val id = it.id //TestCase 注解的属性ID
doSomething(id) //注解处理逻辑
}
}
}
- call函数
另外,如果想通过反射来调用函数,可以直接使用 call():
f.call(sword, id)
//等价于
f.javaMethod?.invoke(sword, id)
//到这里,我们就完成了一个简单的注解处理器,完整的代码如下:
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.EXPRESSION
)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
@MustBeDocumented
annotation class TestCase(val id: String)
class SwordTest {
@TestCase(id = “a”)
fun testCase(testId: String) {
println(“Run SwordTest Id = $testId”)
}
}
fun testAnnoProcessing() {
val sword = SwordTest()
val kClass = sword::class
val members = kClass.members
for (f in members) {
f.annotations.forEach {
if (it is TestCase) {
val id = it.id
doSomething(id)
f.call(sword, id)
}
}
}
}
private fun doSomething(id: String) {
println(“Do Something in Annotation Processing $id ${System.currentTimeMillis()}”)
}
//测试:
main(){
testAnnoProcessing()
}
在Kotlin中我们有两种方式来实现反射功能。
一种是调用Java的反射包下的API
另外一种是 直接调用Kotlin语言提供的 kotlin.reflect包下面的API
不过因为反射功能的应用场景并非所有编程场景都会用到,所以Kotlin把 kotlin.reflect包放到了单独的 kotlin-reflect-1.1.xx.jar下面,也就是说我们如果要使用Kotlin的反射Api,还要去添加依赖。
3.1 类引用
我们先定义一个代码实例:
open class BaseContainer
class Container<T : Comparable> : BaseContainer {
val elements: MutableList
constructor(elements: MutableList) {
this.elements = elements
}
fun sort(): Container {
elements.sort()
return this
}
override fun toString(): String {
return “Container(elements = $elements)”
}
}
反射是在陨石时获取一个类引用。我们已经知道使用 ::class
可以获取到当前对象KClass对象。
val container = Container(mutableListOf(1, 3, 2, 5, 4, 7, 6))
val kClass = container::class
//如果是要使用Java中的类引用,就要使用javaClass
val jClass = container.javaClass
//或者使用KClass实例的.java属性
val jkClass = kClass.java
3.2 函数引用
例如,有一个简单地判断一个Int整数是否是奇数的函数:
fun isOdd(x: Int) = x % 2 != 0
//代码中调用
isOdd(4)
false
另外,在高阶函数中如果想把它当做一个参数来使用,可以使用 ::
操作符
val nums = listOf(1, 2, 3)
val filteredNums = nums.filter(::isOdd)
println(filteredNums) //输出 [1,3]
这里的 ::isOdd
就是一个函数类型 (Int)->Boolean 值
3.3 属性引用
在Kotlin中,访问属性属于第一级对象,可以使用 "::"操作符
var one = 1
fun testReflectProperty() {
println(::one.get())
::one.set(2)
println(one)
}
表达式 ::one 等价于类型为KProperty的一个属性,它可以允许我们通过 get()
函数获取值。
对于可以边属性 var one = 1,返回类型为 KMutableProperty的值,并且还有 set()方法
3.3 绑定函数和属性引用
val digitRegex = “\d+”.toRegex()
digitRegex.matches(“a”)
digitRegex.matches(“4”)
digitRegex.matches(“1”)
digitRegex.matches(“O”)
总结
学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
最后如何才能让我们在面试中对答如流呢?
答案当然是平时在工作或者学习中多提升自身实力的啦,那如何才能正确的学习,有方向的学习呢?有没有免费资料可以借鉴?为此我整理了一份Android学习资料路线:
这里是一部分我工作以来以及参与过的大大小小的面试收集总结出来的一套BAT大厂面试资料专题包,在这里免费分享给大家,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家。需要的小伙伴们可以点击我的GitHub获取免费领取方式
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以去我的主页加一下技术群。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
最后,祝愿即将跳槽和已经开始求职的大家都能找到一份好的工作!
GitHub获取](https://github.com/a120464/Android-P7/blob/master/Android%E5%BC%80%E5%8F%91%E4%B8%8D%E4%BC%9A%E8%BF%99%E4%BA%9B%EF%BC%9F%E5%A6%82%E4%BD%95%E9%9D%A2%E8%AF%95%E6%8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)免费领取方式**
[外链图片转存中…(img-6EhYfl7A-1646557256680)]
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以去我的主页加一下技术群。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
最后,祝愿即将跳槽和已经开始求职的大家都能找到一份好的工作!
这些只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢再关注一下~