教你一文搞懂Kotlin中的Jvm注解

JvmOverloads

创建一个kotlin的类

class Student(val name: String, val sex: Int = 1, val age: Int = 18)

可以看出来 这个构造函数的参数是有默认值的,kotlin的特性对吧,我们在使用的时候可以方便的使用,比如:

 val student = Student("wuyue")
 val student2 = Student("wuyue", age = 18)

但是这个特性如果你用java来调用你就是失败的了。

注意看下面的方法调用是报错的,不能调,只能选择3个构造函数的方法。

那我一定要让java也可以调用 怎么办? 加上注解即可:

class Student @JvmOverloads constructor(val name: String, val sex: Int = 1, val age: Int = 18)

这个对于android程序员来说还是很重要的,比如我们自定义view中 就需要这个注解,否则运行起来 会因为找不到方法而报错的。

所以大家只要谨记一点: 当你的kotlin代码中的某个方法使用了 默认参数值 这个kotlin语言的特性并且这个方法还要给java代码调用的时候那你最好加上JvmOverloads 注解

JvmName

我们给String 增加一个扩展函数 StringsHelper.kt 文件

package com.test
fun String.appendUserName():String{
  return this+"wuyue"
}

在java的世界里 怎么调用他呢?

StringsHelperKt.appendUserName("hello");

很好理解对吧, 但是很多人都习惯于在java的世界中 使用什么xxxUtils 去处理类似的情况。这个时候就要利用到这个JvmName了

@file:JvmName("StringsHelperUtils")
package com.test
fun String.appendUserName():String{
  return this+"wuyue"
}

如此一来 我们在java的世界中 调用他的方法就变成了

StringsHelperUtils.appendUserName("hello");

JvmMultifileClass

关于这个注解 网上的说法是 可以将2个kt文件 里面的代码 合并到一个java的class文件中。

FunA.kt

@file:JvmName("Utils")
@file:JvmMultifileClass

package com.test

fun one(){

}

FunB.kt

@file:JvmName("Utils")
@file:JvmMultifileClass

package com.test

fun two(){

}

这样在java世界中 调用Utils这个类 就有one和two 2个方法了,但是我自己的实验结果 我就算去掉这个JvmMultifileClass 这个注解也一样可以达到效果。似乎这个注解并没有什么用? 可能是1.3之后的kotlin版本 优化了 JvmName的实现吧。 这里有知道原因的大佬可以指点一下。

JvmField

还是前面这个Student的例子

class Student( val name: String, val sex: Int = 1, val age: Int = 18)

如果在java代码里 你要调用他里面的属性 只能通过get和set 来调用。 但是如果你加上注解

class Student(@JvmField val name: String, val sex: Int = 1, val age: Int = 18)

那他在java的世界中就可以 直接调用了

student.name="hello";

另外还有一个重要的作用是: 在kotlin中, val 并不意味着是常量,只不过val 声明的变量 是没有set方法的,只有get方法。所以给了你一个常量的错觉。 你要真正的 在kotlin中 定义一个常量,只有两种方法:

  1. 在top-level或者object中 使用 const val
  2. 或者使用 @JvmField val(这种方式定义的就是常量了,讲白了你也无法重写val的get方法了)

JvmStatic

class StaticTest{
  companion object{

    const val field1="111"

    val field2="222"

    @JvmField val field3="333"

    fun callNonStatic(){

    }
    @JvmStatic
    fun callStatic(){

    }
  }
}

我们看一下 在java代码中 怎么调用他们 就知道这个注解的实际作用了

  StaticTest.callStatic();
    StaticTest.Companion.callNonStatic();
    String t1 = StaticTest.field1;
    String t2=StaticTest.Companion.getField2();
    String t3=StaticTest.field3;

JvmSynthetic

这个注解用的不多,但是kotlin的许多官方库会用到他 讲白了 如果你写的一个函数你只想给kotlin代码调用 而不想给java的代码调用 那你就在你的函数上面加上这个注解即可

例如:

@file:JvmName("StringsHelperUtils")
package com.test
@JvmSynthetic
fun String.appendUserName():String{
  return this+"wuyue"
}

这样你就会发现 这个函数 你用kotlin正常使用 而java代码里StringsHelperUtils 这个类 是没有这个方法的

到此这篇关于教你一文搞懂Kotlin中的Jvm注解的文章就介绍到这了,更多相关Kotlin Jvm注解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-10-08

Kotlin 的注解类详解及实例

Kotlin 的注解类详解及实例 注解声明 注解是将元数据附加到代码的方法.要声明注解,请将 annotation 修饰符放在类的前面: annotation class Fancy 注解的附加属性可以通过用元注解标注注解类来指定: @Target 指定可以用 该注解标注的元素的可能的类型(类.函数.属性.表达式等): @Retention 指定该注解是否 存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true): @Repeatable 允许 在单个元素上多次

Kotlin 基础教程之注解与java中的注解比较

Kotlin 的注解完全兼容 Java 的注解. 声明注解 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy 可以通过向注解类添加元注解(meta

Kotlin基础学习之Deprecated与Suppress注解使用

前言 在 Java 中通常对一些方法进行一些注解操作,但是很多注解在 Java 代码上没有问题,如果切换到 Kotlin 上时,如果继续使用这些注解就会存在一些问题,本篇主要对比一些常用 Java 注解和 Kotlin 注解使用转换. Deprecated 在 Java 方法中,如果需要废弃一个方法,只需要在方法钱加上 @Deprecated 即可,例如这样: @Deprecated public void test(){ } 但是如果在 Kotlin 代码中直接使用这个注释,就存在问题了: D

Kotlin基础学习之位运算

什么是位运算? 程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内存中的二进制位进行操作.比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算.举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理): 110 AND 1011 ---- 0010 –> 2 由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度

Kotlin基础学习之循环和异常

前言 Kotlin并没有想象中的那么牛逼哄哄,也并不难,我更喜欢把他看做一枚语法糖,所谓的语法糖就是:能够让代码变得更加简单易读的辅助工具.而工具这种东西,看看说明书,实操几遍基本就能掌握,都是记忆性的东西,熟能生巧.如果你的Java基础扎实,看看Kotlin的开发文档,写写Demo,分分钟就上手了. 说到这个Kotlin提升写代码效率,还是谈谈几个最直观简单的例子吧: 1.不用再去 findViewById 或者 @BindView,拿到控件id直接用 2.不用再为 Bean 写一堆 gett

Kotlin基础学习之lambda中return语句详解

前言 当我们爱上lambda并且大范围使用它的时候,我想大家都会被lambda中的return语句狠狠地调戏过,所以今天我们需要一起来揭开lambda中return的神秘面纱. 首先来看一个例子: fun demo() { val indexes = arrayOf(1, 2, 3, 4, 5, 6, 7) indexes.forEach { if (it > 5) { return } println(it) } println("End") } 按照我们的预期,调用demo后

kotlin 官方学习教程之基础语法详解

kotlin 官方学习教程之基础语法详解 Google 在今天的举行了 I/O 大会,大会主要主要展示内有容 Android O(Android 8.0)系统.Google Assistant 语音助手.Google 智能音箱.人工智能.机器学习.虚拟现实等.作为一个 Android 开发者,我关心的当然是 Android O(Android 8.0)系统了,那么关于 Android O 系统的一个重要消息是全面支持 Kotlin 编程语言,使得 Kotlin 成为了 Android 开发的官方

Kotlin 基础教程之类、对象、接口

Kotlin 基础教程之类.对象.接口 Kotlin中类.接口相关概念与Java一样,包括类名.属性.方法.继承等,如下示例: interface A { fun bar() fun foo() { // 可选方法体 } } class Child: A { override fun bar() { // todo } override fun foo() { super.foo() } } class 构造器 Kotlin 中的类可以有一个 主构造器, 以及一个或多个次构造器, 主构造器是类头

java基础之反射和泛型以及注解

 java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型,不能为基本类型. 实现公用的类和方法,对公用的业务进行抽取. 泛型方法/泛型类/泛型接口 public class GenericTest { /** * 泛型声明,定义泛型方法 * @param <T> * @param <K> * @param t * @param k */ p

Kotlin语法学习-变量定义、函数扩展、Parcelable序列化等简单总结

Kotlin语法学习-变量定义.函数扩展.Parcelable序列化等简单总结 今年 Google I/O 2017 开发者大会中,Google 宣布正式把 Kotlin 纳入 Android 程序的官方一级开发语言(First-class language),作为Android开发者,当然要逐步熟悉这门语言,第一步就要从语法开始学习. 在这之前,我们需要了解怎么使用Kotlin编写一个Android应用.对于Android Studio 3.0版本,我们在创建工程的时候直接勾选 Include

kotlin基础教程之类和继承

kotlin基础教程之类和继承 类声明 使用class关键字声明类,查看其声明格式: : modifiers ("class" | "interface") SimpleName typeParameters? primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody)

Kotlin 基础教程之反射

Kotlin 基础教程之反射 概述 反射是语言与库中的一组功能, 可以在运行时刻获取程序本身的信息.在Kotlin中,不仅可以通过发射获取类的信息,同时可以获取函数和属性的信息.也就是说,在在运行时刻得到一个函数或属性的名称和数据类型) 可以通过简单的函数式, 或交互式的编程方式实现. 在Java平台上, 使用反射功能所需要的运行时组件是作为一个单独的JAR文件发布的( kotlinreflect.jar). 这是为了对那些不使用反射功能的应用程序, 减少其运行库的大小. 如果你需要使用反射,