Android kotlin 第四篇 JVM内置注解

146 阅读3分钟

注解

JvmName

@file:JvmName("KKK26")

放在类的最顶层,给当前类换一个名字,jvm 在编译时会替换, 修改 Java类文件名字

@JvmName("XXX") 

可以替换方法的名字

JvmField

@JvmField

给成员添加该标签,剔除私有代码,之后就可以直接调用了。

使 Kotlin 编译器不再对该字段生成 getter/setter 并将其作为公开字段

JvmOverloads

告诉Kotlin编译器为此函数生成替换默认参数值的重载

使用场景如下:

@JvmOverloads
fun goToActivity(
  context: Context?,
  url: String?,
  bundle: Bundle? = null,
  requestCode: Int = -1
) {
}
 

对应的Java代码

public final class AKt {
   @JvmOverloads
   public static final void goToActivity(@Nullable Context context, @Nullable String url, @Nullable Bundle bundle, int requestCode) {
   }
 
   // $FF: synthetic method
   // $FF: bridge method
   @JvmOverloads
   public static void goToActivity$default(Context var0, String var1, Bundle var2, int var3, int var4, Object var5) {
      if ((var4 & 4) != 0) {
         var2 = (Bundle)null;
      }
 
      if ((var4 & 8) != 0) {
         var3 = -1;
      }
 
      goToActivity(var0, var1, var2, var3);
   }
 
   @JvmOverloads
   public static final void goToActivity(@Nullable Context context, @Nullable String url, @Nullable Bundle bundle) {
      goToActivity$default(context, url, bundle, 0, 8, (Object)null);
   }
 
   @JvmOverloads
   public static final void goToActivity(@Nullable Context context, @Nullable String url) {
      goToActivity$default(context, url, (Bundle)null, 0, 12, (Object)null);
   }
 

我们可以看到为了能让Java享受到Koltin的默认参数的特性,使用此注解来生成对应的重载方法。

重载的规则是顺序重载,只有有默认值的参数会参与重载.

JvmStatic

@JvmStatic

给对象的成员添加属性, 变成静态可以直接调用,在KT的半生类companion中,实际生成的是一个静态内部类,

你如果给一个方法添加该标签,实际上外面会生成一个静态方法,但是最终方法里面还是会调用回companion里面,JVM没那么傻生成两个方法

Volatile

//不能对val变量加注解
@Volatile
var volatileStr: String = "volatile"

将带注释属性的JVM支持字段标记为 Volatile,这意味着对此字段的写入立即对其他线程可见.

对应Java中的volatile关键字

Synchronized

kotlin lazy 加载的方法里有线程安全模式 SYNCHRONIZED

val instance: ApkTool by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ApkTool() }
  //一般不这样直接修饰在方法上, 一般使用代码块的方式
  @Synchronized
  fun getSynString(): String = "test"

  fun setSynString(str:String){
  //注意这里使用的是内敛函数来实现的对代码块加锁
      synchronized(this){
          println(str)
      }
  }

Transient

将带注释的属性的JVM支持字段标记为transient,表示它不是对象的默认序列化形式的一部分。

对应Java中的transient关键字

//:Serializable
data class XBean(
    val name: String?,
    val age: Int?,
    //不参与序列化
    @Transient
    val male: Boolean = true
): Serializable
 
//Parcelize(目前还是实验性功能 需要在gradle中配置开启 experimental = true)
@Parcelize
data class XBean(
    val name: String?,
    val age: Int?,
    //不参与序列化
    @Transient
    val male: Boolean = true
)

Throws

@Throws(IOException::class)
fun getData(){
    throw IOException("这是一个测试Exception")
}

JvmMultifileClass

用于标记一个类为多文件的一部分。

这意味着一个类的定义被分散在多个 Kotlin 文件中。这种特性允许你将一个大型类拆分到多个文件中,以提高可读性和管理性。

一般配合 JvmName 定义类的名字

/*** KotlinAnn1.kt ***/
@file:JvmName("KAnn")
@file:JvmMultifileClass

package com.example.kotlinlearning_zlz.zhujie10.ann

fun test1() {
    println("这是 KotlinAnn 1")
}
 
/*** KotlinAnn2.kt ***/
@file:JvmName("KAnn")
@file:JvmMultifileClass

package com.example.kotlinlearning_zlz.zhujie10.ann

fun test2() {
    println("这是 KotlinAnn 2")
}
 
/*** KT.kt ***/
package com.example.kotlinlearning_zlz.zhujie10.ann

fun main(){
    test1()
    test2()
}

KotlinAnn1.kt 和 KotlinAnn2.kt 生成时会合并为一个 KAnn.kt