首页 > 其他分享 >JvmName 注解在 Kotlin 中的应用

JvmName 注解在 Kotlin 中的应用

时间:2022-11-09 23:31:11浏览次数:72  
标签:name Kotlin List JvmName jvm 注解 com example jvmannotationsample


JvmName注解是Kotlin提供的一个可以变更编译器输出的注解,这里简单的介绍一下其使用规则。

应用在文件上

未应用@JvmName



package com.example.jvmannotationsample

import android.net.Uri


fun String.toUri(): Uri {
return Uri.parse(this)
}

当我们在Java中调用上面的toUri方法时



StringExtKt.toUri("https://droidyue.com");

生成的 class 文件名称为



./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/StringExtKt.class

应用@JvmName



@file:JvmName("StringUtil")
package com.example.jvmannotationsample

import android.net.Uri


fun String.toUri(): Uri {
return Uri.parse(this)
}

在Java中调用



StringUtil.toUri("https://droidyue.com");

生成的 class 文件名为



./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/StringUtil.class

作用在方法上



package com.example.jvmannotationsample.jvm_name

@JvmName("isOK")
fun String.isValid(): Boolean {
return isNotEmpty()
}

生成的对应的class 文件,我们可以看到方法名称已经修改了。



javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/jvm_name/OnMethodSampleKt.class
Compiled from "OnMethodSample.kt"
public final class com.example.jvmannotationsample.jvm_name.OnMethodSampleKt {
public static final boolean isOK(java.lang.String);
Code:
0: aload_0
1: ldc #11 // String $this$isValid
3: invokestatic #17 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: aload_0
7: checkcast #19 // class java/lang/CharSequence
10: astore_1
11: iconst_0
12: istore_2
13: aload_1
14: invokeinterface #23, 1 // InterfaceMethod java/lang/CharSequence.length:()I
19: ifle 26
22: iconst_1
23: goto 27
26: iconst_0
27: ireturn
}

所以,我们在Java代码中,可以这样调用



public static void testJvmNameOnMethod() {
OnMethodSampleKt.isOK("");
}

但是,我们在Kotlin代码中,还是只能使用​​isValid​​​而不是​​isOK​



fun testJvmNameOnMethod() {
"".isValid()
// "".isOK() unresolved reference
}

那么问题就奇怪了,生成的class里面的方法是​​isOK​​​,怎么还能调用​​isValid​​呢?



javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/jvm_name/KotlinPlaygroundKt.class
Compiled from "KotlinPlayground.kt"
public final class com.example.jvmannotationsample.jvm_name.KotlinPlaygroundKt {
public static final void testJvmNameOnMethod();
Code:
0: ldc #8 // String
2: invokestatic #14 // Method com/example/jvmannotationsample/jvm_name/OnMethodSampleKt.isOK:(Ljava/lang/String;)Z
5: pop
6: return
}

是的,Kotlin编译器将​​isValid​​​在字节码层面又替换成了​​isOK​​。

关于@JvmName作用到方法上,比较好的例子(来自Kotlin官网)是这样的



fun List<String>.filterValid(): List<String> {
TODO()
}

fun List<Int>.filterValid(): List<Int> {
TODO()
}
~/JVMAnnotationSample/app/src/main/java/com/example/jvmannotationsample/jvm_name/GenericList.kt: (3, 1): Platform declaration clash: The following declarations have the same JVM signature (filterValid(Ljava/util/List;)Ljava/util/List;):
fun List<Int>.filterValid(): List<Int> defined in com.example.jvmannotationsample.jvm_name in file GenericList.kt
fun List<String>.filterValid(): List<String> defined in com.example.jvmannotationsample.jvm_name in file GenericList.kt

上面的两个方法声明会导致Kotlin编译出错,因为

由于JVM对于泛型采取了类型擦除,​​List<Int>.filterValid()​​​和​​List<String>.filterValid()​​​实际上对应的都是​​List.filterValid()​

所以,对应的解决方法

  • 修改两个的方法名称,比如​​List<String>.filterValid()​​​修改成​​List<String>.filterValidString()​​等
  • 第二种就是使用@JvmName达到第一种方法的效果

具体修改如下所示



package com.example.jvmannotationsample.jvm_name

@JvmName("filterValidString")
fun List<String>.filterValid(): List<String> {
TODO()
}

@JvmName("filterValidInt")
fun List<Int>.filterValid(): List<Int> {
TODO()
}

作用在属性上

除此之外,@JvmName还可以作用在属性上。比如



package com.example.jvmannotationsample.jvm_name

@get:JvmName("x")
@set:JvmName("changeX")
var x: Int = 23

在Java中对应的调用



public static void testJvmNameOnProperty() {
OnPropertiesSampleKt.changeX(111);
OnPropertiesSampleKt.x();
}

在Kotlin中对应的调用



fun testJvmNameOnProperty() {
x = 1111
x
}

和作用在方法上一样,其实现原理一致,具体如下面的反编译代码可见一斑。

Java调用处的代码



javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/jvm_name/OnPropertiesSampleKt.class
Compiled from "OnPropertiesSample.kt"
public final class com.example.jvmannotationsample.jvm_name.OnPropertiesSampleKt {
public static final int x();
Code:
0: getstatic #11 // Field x:I
3: ireturn

public static final void changeX(int);
Code:
0: iload_0
1: putstatic #11 // Field x:I
4: return

static {};
Code:
0: bipush 23
2: putstatic #11 // Field x:I
5: return
}

Kotlin调用处的代码



javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/jvm_name/KotlinPlaygroundKt.class
Compiled from "KotlinPlayground.kt"
public final class com.example.jvmannotationsample.jvm_name.KotlinPlaygroundKt {


public static final void testJvmNameOnProperty();
Code:
0: sipush 1111
3: invokestatic #36 // Method com/example/jvmannotationsample/jvm_name/OnPropertiesSampleKt.changeX:(I)V
6: invokestatic #40 // Method com/example/jvmannotationsample/jvm_name/OnPropertiesSampleKt.x:()I
9: pop
10: return
}

相关文章


标签:name,Kotlin,List,JvmName,jvm,注解,com,example,jvmannotationsample
From: https://blog.51cto.com/u_3987305/5838995

相关文章

  • 01-SpringBoot注解
    SpringBoot注解Spring常用注解配置注解含义@Configuration定义一个类是Spring配置类@Bean配置自定义的Bean,如DruidDataSource@Componen......
  • SpringCloud(八) - 自定义token令牌,鉴权(注解+拦截器),参数解析(注解+解析器)
    1、项目结构介绍项目有使用到,redis和swagger,不在具体介绍;2、手动鉴权和用户信息参数获取(繁杂,冗余)2.1用户实体类/***CreatedOn:4/11/2022.*<p>*Author......
  • 自定义注解及使用
    自定义注解及使用定义一个自定义注解importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy......
  • spring boot Swagger2(version=2.7.0) 注解@ApiImplicitParam的属性dataType值为”自
    转载自:https://www.bbsmax.com/A/WpdKlbDqzV/注解:@ApiImplicitParams@ApiImplicitParam   name="需注解的API输入参数",value="接收参数的意义描述",paramType="参......
  • @ApiImplicitParam注解的dataType、paramType两个属性的区别?
    dataType="int"代表请求参数类型为int类型,当然也可以是Map、User、String等;paramType="body"代表参数应该放在请求的什么地方:  header-->放在请求头。请求参数的......
  • kotlin中ViewModel + ViewBinding使用实例
    android使用androidx后可以使用viewbinding了,因为是内生库,也蛮好用的。butterknife感觉已经在退环境了。文章列出ViewModel+ViewBinding,是MVVM模式的简单使用,没有涉及......
  • 纯手写线程池+async注解实现异步任务
    spring整合多线程---@Async注解基本配置启动添加注解@SpringBootApplication@EnableAsyncpublic class Demo000Application {    public static void m......
  • mybatis注解开发无法查询中文(这个bug卡了我两周了)
    泪目了,两周了,终于解决了Mapper里面的SQL注解语句  Postman发送请求  查询不到数据,  控制台里面语句正确的,参数是正确的,没有乱码,我把语句从控制台复制到co......
  • TestNg注解
    packagetest;importorg.testng.annotations.Optional;importorg.testng.annotations.Parameters;importorg.testng.annotations.Test;publicclasstest01{......
  • ES6的详细注解
    let声明变量的新方法。变量无法重复声明。块级作用域。也就是说let只在代码块中生效,包括if、else等花括号中的变量不会定义到全局。不存在变量提升。也就是说,在声明变量之前......