美文网首页
从Java调用Kotlin代码

从Java调用Kotlin代码

作者: 慎独静思 | 来源:发表于2024-03-22 07:32 被阅读0次

在平时开发中不可避免的需要从Java调用Kotlin,今天就学习一下哪些是Java调用Kotlin更加方便的注解。

@JvmStatic

object StringUtil {
    init {
        println()
    }
    
    fun changeTo(value: String) {

    }
}

StringUtil.INSTANCE.changeTo(data);

在Java中调用对象声明中的方法时,需要带INSTANCE,不像调用Java静态方法,直接使用类名+方法名,因为Kotlin反编译生成的Java代码就有一个静态INSTANCE实例

public final class StringUtil {
   @NotNull
   public static final StringUtil INSTANCE;

   public final void changeTo(@NotNull String value) {
      Intrinsics.checkNotNullParameter(value, "value");
   }

   private StringUtil() {
   }

   static {
      StringUtil var0 = new StringUtil();
      INSTANCE = var0;
      System.out.println();
   }
}

通过这个实例,可以直接调用类中的方法,如果我们想像调用Java方法那样调用Kotlin 对象声明的方法,应该怎么办呢,此时就需要用到@JvmStatic注解。

object StringUtil {
    init {
        println()
    }
    
    @JvmStatic
    fun changeTo(value: String) {

    }
}

StringUtil.changeTo(data);

添加@JvmStatic之后可以通过类名直接调用方法,反编译之后的Java代码是什么样呢?

public final class StringUtil {
   @NotNull
   public static final StringUtil INSTANCE;

   @JvmStatic
   public static final void changeTo(@NotNull String value) {
      Intrinsics.checkNotNullParameter(value, "value");
   }

   private StringUtil() {
   }

   static {
      StringUtil var0 = new StringUtil();
      INSTANCE = var0;
      System.out.println();
   }
}

changeTo方法变成了静态方法,由此,我们可知@JvmStatic的作用。
@JvmStatic可以用来修饰方法或属性,声明为所注释的方法生成对应的静态方法,为所注释的属性生成静态的getter/setter。

@JvmName

@JvmName可以指定Kotlin生成的字节码中类,属性和方法的命名方式。
我们创建一个Kotlin文件StringUtil.kt,一个顶层函数


package com.lkk.kotlinbasic.myapp

fun changeTo(name: String) {
    println(name)
}

StringUtilKt.changeTo("hello");

默认生成的类名为StringUtilKt,反编译后的Java代码如下:

public final class StringUtilKt {
   public static final void changeTo(@NotNull String name) {
      Intrinsics.checkNotNullParameter(name, "name");
      System.out.println(name);
   }
}

接下来我们使用@JvmName指定生成的类名

@file:JvmName("StringUtil")
package com.lkk.kotlinbasic.myapp

fun changeTo(name: String) {
    println(name)
}

反编译之后的Java代码如下

public final class StringUtil {
   public static final void changeTo(@NotNull String name) {
      Intrinsics.checkNotNullParameter(name, "name");
      System.out.println(name);
   }
}

生成的类名正是咱们指定的类名。
@JvmName同样可以用来注解属性

class User {
    val hasSystemAccess
        get() = ""
}

我们在Java中调用时只能使用user.getHasSystemAccess(),如果我们想修改自动生成get方法的名称,可以使用@JvmName,这里有两种写法

class User {
    val hasSystemAccess
        @JvmName("hasSystemAccess")
        get() = ""
}

class User {
    @get:JvmName("hasSystemAccess")
    val hasSystemAccess
        get() = ""
}

这两种方式都能实现咱们得目的,参考最终生成的Java代码

public final class User {
   @JvmName(
      name = "hasSystemAccess"
   )
   @NotNull
   public final String hasSystemAccess() {
      return "";
   }
}

通过使用 @JvmName 注解,Kotlin 会为带注解的项生成具有指定名称(而非默认名称)的字节码,同样可以使用@set:JvmName来修改setter的名称,此处不再赘述。

@JvmOverloads

Kotlin支持参数默认值,但Java不支持,从Java调用Kotlin带默认值的构造方法或函数时需要使用@JvmOverloads注解。

class User(name: String = "hello") {
    @JvmOverloads
    fun printUser(name: String, age: Int = 18) {
        print("$name, $age")
    }
}
   @JvmOverloads
   public final void printUser(@NotNull String name) {
      printUser$default(this, name, 0, 2, (Object)null);
   }

   @JvmOverloads
   public final void printUser(@NotNull String name, int age) {
      Intrinsics.checkNotNullParameter(name, "name");
      String var3 = name + ", " + age;
      System.out.print(var3);
   }

给方法printUser添加@JvmOverloads之后,生成了这个方法的重载版本。现在在Java代码中既可以调用printUser(@NotNull String name) ,也可以调用printUser(@NotNull String name, int age),没提交@JvmOverloads,只能调用printUser(@NotNull String name, int age)。
我试了一下给构造方法添加@JvmOverloads,添加之前和添加之后好像没有区别。

@JvmField

@JvmField用来注解属性,添加注解之后Kotlin不会为其自动生成getter/setter,并把它作为一个属性暴露。

class User @JvmOverloads constructor(@JvmField val id: Int, name: String = "hello") {
    @JvmOverloads
    fun printUser(name: String, age: Int = 18) {
        print("$name, $age")
    }
}

我们为id属性添加了@JvmField注解,可以看到反编译之后的Java代码并没有对应的getter/setter,并且在Java代码中可以直接调用id,而不需要使用getter方法。
对于object中的常量,还是建议使用const。

@Throws

Java 中有“受检异常”的概念,但Kotlin 没有受检异常,这就会导致在Java中调用Kotlin抛出受检异常的函数时报错,此时需要抛出@Throws,指示 Java 代码 Kotlin 函数会抛出异常。

fun openFile(filePath: String) {
        val outputFile = File(filePath)
        if (!outputFile.canWrite()) {
            throw FileNotFoundException("Could not write to file: $filePath")
        }
}

user.openFile("");

创建一个抛出异常的方法如上,并在Java侧调用此方法,代码编译时会抛出异常
java.io.FileNotFoundException: Could not write to file:

public final void openFile(@NotNull String filePath) {
      Intrinsics.checkNotNullParameter(filePath, "filePath");
      File outputFile = new File(filePath);
      if (!outputFile.canWrite()) {
         throw (Throwable)(new FileNotFoundException("Could not write to file: " + filePath));
      }
   }

这是编译之后Java代码。

@Throws(IOException::class)
    fun openFile(filePath: String) {
        val outputFile = File(filePath)
        if (!outputFile.canWrite()) {
            throw FileNotFoundException("Could not write to file: $filePath")
        }
    }

我们给openFile添加@Throws(IOException::class)注解,此时看一下反编译之后的Java代码

public final void openFile(@NotNull String filePath) throws IOException {
      Intrinsics.checkNotNullParameter(filePath, "filePath");
      File outputFile = new File(filePath);
      if (!outputFile.canWrite()) {
         throw (Throwable)(new FileNotFoundException("Could not write to file: " + filePath));
      }
   }


try {
            user.openFile("");
        } catch (IOException e) {
            throw new RuntimeException(e);
 }

在函数上添加了throws,此时在Java中再调用此方法,需要try-catch或继续往上抛异常。

Over

参考

  1. 从 Java 调用 Kotlin 代码

相关文章

  • java中调用kotlin代码

    在上一篇博客中,介绍了kotlin调用java代码,这篇文章介绍java调用kotlin代码。 属性 kotlin...

  • Kotlin学习之与Java的互操作

    在 Kotlin 中调用 Java 代码 Kotlin 在设计时就考虑了 Java 互操作性。可以从 Kotlin...

  • method kotlin.jvm.internal.Intri

    场景:java代码调用kotlin方法,kotlin方法参数后边不加?,且实参为null java代码中调用kot...

  • 1.Kotlin Tips

    1.Android Studio允许你轻松地从Kotlin调用Java代码: 2.Kotlin是JetBrains...

  • kotlin特殊地方

    java与kotlin混用并互相调用?? 想kotlin代码中直接使用控件id需要加kotlin拓展插件,kotl...

  • 撸个应用学Android音乐App

    前言 使用Kotlin实现一个简易的本地音乐客户端,部分代码为Java语言,Kotlin可以完美调用Java,En...

  • Kotlin学习笔记之基础语法篇

    一、学习从主函数开始(main) Hello World! Kotlin代码 Java代码 对比: Kotlin不...

  • 单例模式

    一、UML 二、代码 1、实现 2、调用 3、结果 事实证明;1、Kotlin比Java更简洁;2、Kotlin中...

  • Kotlin

    输出hello world Java 代码 Kotlin 代码 定义一个变量 Java 代码 Kotlin 代码

  • 2021-11-30(Kotlin学习笔记)Kotlin 基础(

    kotlin java 隔离 kotlin 扩展函数 java 中调用扩展函数 高级函数

网友评论

      本文标题:从Java调用Kotlin代码

      本文链接:https://www.haomeiwen.com/subject/dkkftjtx.html