大家好,我是青空。今天给大家带来的是kotlin 注解。
文末可领取大厂面试题
注解声明
简介
将 annotation 修饰符放在类的前面
annotation class Fancy
附加属性
-
可以通过用元注解标注注解类来指定
-
属性类型
-
指定该注解是公有 API 的一部分,并且应该包含在生成的 API 文档中显示的类或方法的签名中。 范例
-
允许在单个元素上多次使用相同的该注解;
-
指定该注解是否存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true);
-
指定可以用该注解标注的元素的可能的类型(类、函数、属性、表达式等);
-
@Target
-
@Retention
-
@Repeatable
-
@MustBeDocumented
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
用法
范例
@Fancy class Foo {
@Fancy fun baz(@Fancy foo: Int): Int {
return (@Fancy 1)
}
}
支持 标注 主构造函数
class Foo @Inject constructor(dependency: MyDependency) { …… }
支持 标注 属性访问器
class Foo {
var x: MyDependency? = null
@Inject set
}
构造函数
注解也可以带参数
annotation class Special(val why: String)
@Special("example") class Foo {}
-
允许的参数类型
-
对应于 Java 原生类型的类型(Int、 Long等);
-
字符串;
-
类(Foo::class);
-
枚举;
-
其他注解;
-
上面已列类型的数组。
注意
-
注解参数不能有可空类型
-
JVM 不支持将 null 作为注解属性的值存储
-
注解支持嵌套使用
-
即 注解A 用作注解B 的参数
-
其名称不以 @ 字符为前缀
看个范例
annotation class ReplaceWith(val expression: String)
annotation class Deprecated(
val message: String,
val replaceWith: ReplaceWith = ReplaceWith(""))
@Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
一个类 也可以 作用注解的参数
-
需要使用 Kotlin 类 (KClass)
-
Kotlin 编译器会自动将其转换为 Java 类
-
进一步理解一下
-
为什么最终还是java类呢?再想一下
-
为什么Kotlin能兼容java呢?
-
我们可以大胆假设一下,Kotlin的兼容,其实是在编译期的。编译器将Kotlin转换成java,所以,支持了java。
-
细心的朋友应该有注意到
-
很多Kotlin实现的东西,其实用java绕来绕去也可以实现。Kotlin胜在简便。而这个简便到底是怎么来的呢?
-
是编译器的转换。编译器处理了之前需要手动实现的繁杂的事务。
-
这也是为什么Kotlin能很好的兼容Android、IOS、JavaScript的原因。
-
Kotlin是Java、OC、JS包装后的实现
范例
import kotlin.reflect.KClass
annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any>)
@Ann(String::class, Int::class) class MyClass
Lambda 表达式
-
注解也可以用于 lambda 表达式
-
会被应用于生成 lambda 表达式体的 invoke() 方法
看范例,使用注解的并发控制
annotation class Suspendable
val f = @Suspendable { Fiber.sleep(10) }
注解使用处目标
注解可以通过一系列@XXX更精确的生成所需注解
class Example(@field:Ann val foo, // 标注 Java 字段
@get:Ann val bar, // 标注 Java getter
@param:Ann val quux) // 标注 Java 构造函数参数
支持的使用处目标的完整列表
-
file;
-
property(具有此目标的注解对 Java 不可见);
-
field;
-
get(属性 getter);
-
set(属性 setter);
-
receiver(扩展函数或属性的接收者参数);
-
param(构造函数参数);
-
setparam(属性 setter 参数);
-
delegate(为委托属性存储其委托实例的字段)。
若希望使用相同的预发标注整个文件
@file:JvmName("Foo")
package org.jetbrains.demo
- 把带有目标 file 的注解放在文件的顶层、package 指令之前或者在所有导入之前
标注 扩展函数的接收者 参数
fun @receiver:Fancy String.myExtension() { ... }
-
接收者参数是什么呢?
-
fun notify(User user) {}
-
notify它是值接收者方法
-
这个说法在GoLang看到比较多
-
顾名思义,就是 被赋值、被传参、被XXX的
-
范例
Java 注解
首先
-
Java 注解与 Kotlin 100% 兼容
-
我们来看个范例对比
java
// Java
public @interface Ann {
int intValue();
String stringValue();
}
kotlin
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C
-
注意
-
它的值无需显式名称指定
-
看个范例
-
若参数只有一个value()
java
public @interface AnnWithValue {
String value();
}
kotlin
// Kotlin
@AnnWithValue("abc") class C
数组作为注解参数
如果 Java 中的 value 参数具有数组类型
java
// Java
public @interface AnnWithArrayValue {
String[] value();
}
value()是可以省略 显式的使用 参数名的:value
kotlin
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C
如果这里value换个名字,改成names,则需要显式的使用
范例
// Java
public @interface AnnWithArrayMethod {
String[] names();
}
// Kotlin 1.2+:
@AnnWithArrayMethod(names = ["abc", "foo", "bar"])
class C
// 旧版本 Kotlin:
@AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar"))
class D
访问注解实例的属性
-
注解实例的值会作为属性暴露给 Kotlin 代码
-
java的注解会以属性的方式暴露给kotlin
范例
- // Java
public @interface Ann {
int value();
}
- // Kotlin
fun foo(ann: Ann) {
val i = ann.value
}
最近又赶上跳槽的高峰期,好多粉丝,都问我有没有最新大厂面试题,我连日加班好多天,终于整理好了,1000+ 道,20多份大厂面试题大全,我会持续更新中!公众号回复【面试题】即可获取。