IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin常?注解 -> 正文阅读

[移动开发]Kotlin常?注解

1.@JvmName

这个注解可以改变字节码中生成的类名或方法名称,如果作用在顶级作用域(文件中),则会生成对应的Java类的名称。如果作用在方法上,则会改变生成对应Java方法的名称。

Test.kt

@file:JvnName("FooKt")

@file:JvnName("foo1")
fun foo(){
pritln("hellow,JVM")
}

在Kolin语言中,foo是一个全局方法,为了兼容Java字节码,实际会根据文件名生成对应的Java类TestKt.java.这是Kotlin编译器的一个隐藏规则。
而添加了注解之后,生产的类名与方法名均发生了变化,具体产生的变化相当于下面这段Java代码:

//相当于下面的Java代码
public final class FooKt{
	public static final void foo1(){
		String var0="Hellow,Jvm...";
		System.out.println(car0);
	}
}

可以看到第一个注解@file:JvnName(“FooKt”)的作用是使生成的类名变成FooKt,第二个注解的作用是使生成的方法名称变为foo1.
注意:该注解不能改变类中生成的属性(成员变量)的名称
这里的注解中,我们看到了一个特殊的前缀@file:这个注解前缀是Kotlin语言特有的一种标识,其作用是标记该注解最终会作用在生成的字节码的具体位置(属性,setter,getter等)

2.@JvmMultifileClass

说完了上面这个注解,就不得不提到@JvmMultifileClass这个注解,这个注解通常是与@JvmName结合使用的。其使用场景比较单一,看下面的例子:
新建文件Util1.kt,添加如下代码:

@file:JvmName("Utils")
fun isEmpty(str:String?):Boolean{
	return null==str ||str.length<=0
}

新建文件Util2.kt,添加如下代码:

@file:JvmName("Utils")
fun isPhoneNumber(str:String):Boolean{
	return str.startWith("1") &&str.length ==1
}

编译以上代码,Kotlin编译器会提示错误 Error:Error:(1, 1) Kotlin: Duplicate JVM class name ‘Utils’ generated from: package-fragment, package-fragment ,即生成的类名出现了重复。可是,如果我们就是洗碗声明使用多个文件,但方法生成到同一个类中呢?@JvmMultifileClass 就是为了解决这个问题而生的。
我们在上面代码的基础上分别添加注解@JvmMultifileClass 试试看:

@file:JvmName("Utils")
@JvmMultifileClass

fun isEmpty(str:String?):Boolean{
	return null==str ||str.length<=0
}
@file:JvmName("Utils")
@JvmMultifileClass

fun isPhoneNumber(str:String):Boolean{
	return str.startWith("1") &&str.length ==1
}

添加@JvmMultifileClass之后,报错消失了,反编译生成的字节码,我们发现两个不同文件中的方法合并到了同一类 Utils中:

//生成的代码相当于下面这段Java代码
public final class Utils{
	public static final boolean isEmpty(@Nullable String str){
		return Utils_A1Kt.isEmpty(str);
	}
	public static final boolean isPhoneNumber(@Nullable String str){
		return Utils_A2Kt.isPhoneNumber(str);
	}
}

这个注解在处理多个文件声明,合并到一个类的场景中发挥着举足轻重的作用。如果你有这样的需求,一定要谨记这个注解。

3.@JvmOverloads

由于Kotlin语言支持方法参数默认值,而是类似功能Java需要使用方法重载来实现,这个注解就是为了解决这个问题而生的,添加这个注解会自动生成重载方法,我们来试一下:

@JvmOverloads
fun foo(x:Int,yL:Int=0,z:Int=0):Int{
	return x + y + z
}
//生成你的代码相当于下面这段Java代码
puiblic static final int foo(int x,int y ,int z){
	return x + y + z
}
puiblic static final int foo(int x,int y){
	return foo(x,y,0)
}
puiblic static final int foo(int x){
	return foo(x,0,0)
}

由此可见,通过这个注解可以影响带参数默认值方法的生成,改加该注解将自动生成带有默认值参数数量的重载方法。这个一个分厂有用的特性,方便java端可以更高效地调用Kotlin端代码。

4.@Thows

由于Kotlin不支持CE(Checked Exception),作为CE,即方法可能抛出的异常是已知的。Java语言通过throws关键字在方法上声明CE。为了兼容这种写法,Kotlin语言新增了@Throws注解,该注解接受一个可变的参数,参数类型是多个异常KClass实例。Kotin编译器通过读取注解参数,在生成的字节码中自动添加CE声明。
为了便于理解,看一个简单的例子:
@Throws(IIIegalArgumentException::class)
fun div(v:Int,y:Int):Float{
return x.toFloat()/y
}

//生成的代码相当于下面这段Java代码
public stativ final float div(int x,int y)throws IIegalArgumentException{
return (float)x / (float)y;
}

5.@Synchionized

这个注解很容易理解,顾名思义,主要用于产生同步方法。Kotliln语言不支持synchionized关键字,处理类似Java语言的并发问题,Kotlin语言建议使用同步方法进行处理。
但为了兼容Java,Kotlin语言支持使用该注解让编译器自动生成同步方法:

@Synchionized
fun start(){
	println("start do domething ...")
}
//生成的代码相当于下面这段Java代码
public static final synchronized void start(){
	String var0="start do domething ...";
	System.out.println(var0);
}

6.@JvmWildcard

这个注解主要用于处理泛型参数,这涉及到两个新的知识点:逆变与协变,为了保证安全地相互调用,可以通过在泛型参数声明的位置添加该注解使用Kotlin编译器生成通配符形式的泛型参数(? extends …)。
看下面这段代码:

class Box<out T>(val value:T)

interface Base
class Derived:Base

fun boxDerived(value:Derived):Box<Derived>=Box(value)
fun unboxBase(box:Box<Base>):Base = box.value

按照正常的思维,下面的两个方法转换到Java代码应该是这样

Box<Derived> boxDerived(Derived value){......}
Base unboxBase(Box<Base> box){......}

为了使这样的转换正确生成,我们需要在泛型参数的位置添加上面的注解:

fun unboxBase(box:Box<@JvmWildcard Base>):Base =box.value

但问题是,Kotlin泛型支持型变,在Kotlin 中,我们可以这样写 unboxBse(Box(Derived())),而在Java语言中,泛型参数类型是不可变的,按照上面的写法显然已经做不到了。

正确转到Java代码应该是这样:

Base unboxBase(Base<? extends Base> box){......}

7.@JvmSuppressWildcards

这个注解的作?与@JvmWildcard恰恰相反,它是?来抑制通配符泛型参数的?成,即在不需要型变泛型参数的情况下,我们可以通过添加这个注解来避免生成型变泛型参数。

fun unboxBase(box:Box<@JvmSuppressWildcards Base>):Base=box.value
//生成的代码相当于下面这段Java代码
Base unboxBase(Box<Base> box){......}

8.@Volatile @Transient

这两个注解恰好对应Java端的两个关键字 volatile 与transient,前者主要用于解决多线程脏数据问题,后者用于标记序列化对象中不参与序列化的属性。
这两个注解比较简答,就不举例说明了。在遇到类似要与Java互通的场景时,只需要将其关键字替换为该注解即可。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-15 11:39:14  更:2022-05-15 11:39:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:36:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码