[Kotlin] KotlinとJavaの相互運用性② ( @JvmField アノテーションフィールドをJavaへ | @JvmOverloads アノテーション変更機能 | @JvmStatic アノテーションで static メンバを宣言 )





1. @JvmField アノテーションを使用して、Kotlin フィールドを Java に公開します




1. Java クラスの Getter メソッドと Setter メソッドを介して Kotlin フィールドにアクセスする


Kotlin のフィールドはJava で直接アクセスできず対応する Getter メソッドと Setter メソッドを呼び出してアクセスする必要があります。


コード例:


Kotlin クラス: Kotlin で宣言されたメンバー プロパティは、デフォルトでプライベート プライベート プロパティであり、Getter メソッドと Setter メソッドがデフォルトで生成されます。

class Hello {
    
    
    var name = "Tom"
}

Java クラスからの直接呼び出し: Java クラスでは、Kotlin フィールドを直接呼び出すことはできません。

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        Hello hello = new Hello();
        System.out.println(hello.name);
    }
}

Java クラスでエラーが報告されます。

'name' has private access in 'Hello'

ここに画像の説明を挿入


Java クラスでは、Kotlin フィールドはGetter メソッドと Setter メソッドを介してのみ呼び出すことができます。

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        Hello hello = new Hello();
        System.out.println(hello.getName());
    }
}

の結果:
ここに画像の説明を挿入


2. Java クラスの @JvmField アノテーションで装飾された Kotlin フィールドへの直接アクセス


@JvmField アノテーションを使用してKotlin のメンバー プロパティを変更する場合その機能は Kotlin フィールドを Java に公開することでありGetter および Setter メソッドを使用せずに。


コトリンコード:

class Hello {
    
    
    @JvmField
    var name = "Tom"
}

Java コード:

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        Hello hello = new Hello();
        System.out.println(hello.name);
    }
}

の結果:

ここに画像の説明を挿入

@JvmField アノテーションは、Kotlin でフィールドを Java フィールドとして宣言するの。この時点で、Kotlin はフィールドの Getter および Setter メソッドを自動的に生成しません。





2. @JvmOverloads アノテーションを使用して、Kotlin 関数を変更します。



Kotlin では、関数パラメーターは独自のデフォルト値を持つことができ、呼び出し時に目的のパラメーターを直接。

ただし、Java がKotlin 関数を呼び出すとき、 Java 言語はデフォルト値を持つ関数パラメーターの構文をサポートしていません. 指定されたパラメーターが渡される場合、関数をオーバーロードする必要があります。

@JvmOverloads アノテーションを使用して Java ユーザー向けに一連のオーバーロードされた関数が自動的に実装されます;
たとえば、パラメーター リストが ( String , age ) の場合、 @JvmOverloads アノテーションを使用して関数を変更すると、自動的に

  • 0 パラメータ、
  • 1 パラメータ、
  • 2つのパラメータ

関数 ;


1. Kotlin デフォルトパラメータ関数呼び出し例


Kotlin コード例: In the following helloStudentfunction , both parameters are set with default parameter values . Kotlin でこの関数を呼び出す場合、0、1、および 2 つのパラメーターを渡すことができ、渡す場合に渡すパラメーターを選択できます。 1 つのパラメーター。

class Hello {
    
    
    fun helloStudent(name: String = "Tom", age: Int = 18) {
    
    
        println("Student $name is $age years old , say hello !")
    }
}

fun main() {
    
    
    var hello = Hello();
    hello.helloStudent()
    hello.helloStudent("Jerry")
    hello.helloStudent(age = 22)
    hello.helloStudent("Bill", 12)
}

の結果:

Student Tom is 18 years old , say hello !
Student Jerry is 18 years old , say hello !
Student Tom is 22 years old , say hello !
Student Bill is 12 years old , say hello !

ここに画像の説明を挿入

上記の Kotlin コードのバイトコード データを分析し、Kotlin バイトコードでバイトコード データを表示し、次のように Java コードに逆コンパイルします。

// Hello.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 1,
   d1 = {
    
    "\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001a\u0010\u0003\u001a\u00020\u00042\b\b\u0002\u0010\u0005\u001a\u00020\u00062\b\b\u0002\u0010\u0007\u001a\u00020\b¨\u0006\t"},
   d2 = {
    
    "LHello;", "", "()V", "helloStudent", "", "name", "", "age", "", "KotlinDemo"}
)
public final class Hello {
    
    
   public final void helloStudent(@NotNull String name, int age) {
    
    
      Intrinsics.checkParameterIsNotNull(name, "name");
      String var3 = "Student " + name + " is " + age + " years old , say hello !";
      boolean var4 = false;
      System.out.println(var3);
   }

   // $FF: synthetic method
   public static void helloStudent$default(Hello var0, String var1, int var2, int var3, Object var4) {
    
    
      if ((var3 & 1) != 0) {
    
    
         var1 = "Tom";
      }

      if ((var3 & 2) != 0) {
    
    
         var2 = 18;
      }

      var0.helloStudent(var1, var2);
   }
}
// HelloKt.java
import kotlin.Metadata;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 2,
   d1 = {
    
    "\u0000\b\n\u0000\n\u0002\u0010\u0002\n\u0000\u001a\u0006\u0010\u0000\u001a\u00020\u0001¨\u0006\u0002"},
   d2 = {
    
    "main", "", "KotlinDemo"}
)
public final class HelloKt {
    
    
   public static final void main() {
    
    
      Hello hello = new Hello();
      Hello.helloStudent$default(hello, (String)null, 0, 3, (Object)null);
      Hello.helloStudent$default(hello, "Jerry", 0, 2, (Object)null);
      Hello.helloStudent$default(hello, (String)null, 22, 1, (Object)null);
      hello.helloStudent("Bill", 12);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
    
    
      main();
   }
}

2. Java で Kotlin のデフォルト パラメータ関数を呼び出す


KotlinなどのJava コードで任意の数と型のパラメーターを渡したい場合は関数のオーバーロードを使用する必要があります。

Kotlin のように直接呼び出された場合、間違いなくエラーが報告されます。
ここに画像の説明を挿入

@JvmOverloads アノテーションを使用して Kotlin 関数を変更すると、Java ユーザー向けに一連のオーバーロードされた関数が自動的に実装されます。


Kotlin コード例:

class Hello {
    
    
    @JvmOverloads
    fun helloStudent(name: String = "Tom", age: Int = 18) {
    
    
        println("Student $name is $age years old , say hello !")
    }
}

fun main() {
    
    
    var hello = Hello();
    hello.helloStudent()
    hello.helloStudent("Jerry")
    hello.helloStudent(age = 22)
    hello.helloStudent("Bill", 12)
}

Java コード例:

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        Hello hello = new Hello();
        hello.helloStudent();
        hello.helloStudent("Jerry");
        hello.helloStudent("Bill", 12);
    }
}

の結果:

Student Tom is 18 years old , say hello !
Student Jerry is 18 years old , say hello !
Student Bill is 12 years old , say hello !

ここに画像の説明を挿入

@JvmOverloads でアノテーションが付けられた Kotlin クラスに対応する上記のバイトコード データを分析し、バイトコードを Java コードに逆コンパイルします。内容は次のとおりです。

// Hello.java
import kotlin.Metadata;
import kotlin.jvm.JvmOverloads;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 1,
   d1 = {
    
    "\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001c\u0010\u0003\u001a\u00020\u00042\b\b\u0002\u0010\u0005\u001a\u00020\u00062\b\b\u0002\u0010\u0007\u001a\u00020\bH\u0007¨\u0006\t"},
   d2 = {
    
    "LHello;", "", "()V", "helloStudent", "", "name", "", "age", "", "KotlinDemo"}
)
public final class Hello {
    
    
   @JvmOverloads
   public final void helloStudent(@NotNull String name, int age) {
    
    
      Intrinsics.checkParameterIsNotNull(name, "name");
      String var3 = "Student " + name + " is " + age + " years old , say hello !";
      boolean var4 = false;
      System.out.println(var3);
   }

   // $FF: synthetic method
   public static void helloStudent$default(Hello var0, String var1, int var2, int var3, Object var4) {
    
    
      if ((var3 & 1) != 0) {
    
    
         var1 = "Tom";
      }

      if ((var3 & 2) != 0) {
    
    
         var2 = 18;
      }

      var0.helloStudent(var1, var2);
   }

   @JvmOverloads
   public final void helloStudent(@NotNull String name) {
    
    
      helloStudent$default(this, name, 0, 2, (Object)null);
   }

   @JvmOverloads
   public final void helloStudent() {
    
    
      helloStudent$default(this, (String)null, 0, 3, (Object)null);
   }
}
// HelloKt.java
import kotlin.Metadata;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 2,
   d1 = {
    
    "\u0000\b\n\u0000\n\u0002\u0010\u0002\n\u0000\u001a\u0006\u0010\u0000\u001a\u00020\u0001¨\u0006\u0002"},
   d2 = {
    
    "main", "", "KotlinDemo"}
)
public final class HelloKt {
    
    
   public static final void main() {
    
    
      Hello hello = new Hello();
      Hello.helloStudent$default(hello, (String)null, 0, 3, (Object)null);
      Hello.helloStudent$default(hello, "Jerry", 0, 2, (Object)null);
      Hello.helloStudent$default(hello, (String)null, 22, 1, (Object)null);
      hello.helloStudent("Bill", 12);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
    
    
      main();
   }
}

@JvmOverloads アノテーションを使用した後、 0、1、および 2 つのパラメーターを持つオーバーロードされた関数が
、コンパイル時にhelloStudent 関数に対して自動的に生成されるため、これらのメソッドをJava で呼び出すときに直接呼び出すことができます。

   @JvmOverloads
   public final void helloStudent(@NotNull String name, int age) {
    
    
      Intrinsics.checkParameterIsNotNull(name, "name");
      String var3 = "Student " + name + " is " + age + " years old , say hello !";
      boolean var4 = false;
      System.out.println(var3);
   }

   @JvmOverloads
   public final void helloStudent(@NotNull String name) {
    
    
      helloStudent$default(this, name, 0, 2, (Object)null);
   }

   @JvmOverloads
   public final void helloStudent() {
    
    
      helloStudent$default(this, (String)null, 0, 3, (Object)null);
   }




3. @JvmStatic アノテーションを使用して静的メンバーを宣言する



In Kotlin, there is no concept of static members . static member を宣言する必要がある場合、通常はその Companion コンパニオン オブジェクトで宣言されます。

JavaKotlin の Companion コンパニオン オブジェクトのメンバーを呼び出す場合は、次の形式で呼び出す必要があります。

Kotlin.Companion.成员属性
Kotlin.Companion.成员函数

Companion を使用せずにKotlin で Companion コンパニオン オブジェクト メンバーを直接呼び出したい 場合は

コンパニオン オブジェクトに含めることができます

@JvmStatic アノテーションを使用して 、コンパニオン オブジェクトのメンバーを Java 静的メンバーとして宣言します。

Java では、静的メンバーとしてアクセスできます。


1. Java は通常、Kotlin コンパニオン オブジェクト メンバーにアクセスします。


次のコードでは、Java 言語で Kotlin のコンパニオン オブジェクトのメンバーにアクセスするには、最初に Hello.Companion クラスのコンパニオン オブジェクトを取得してから、コンパニオン オブジェクトのメンバーにアクセスする必要があります。


コトリンコード:

class Hello {
    
    
    companion object {
    
    
        var name = "Tom"
        fun say() {
    
    
            println("Hello World")
        }
    }
}

Java コード:

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(Hello.Companion.getName());
        Hello.Companion.say();
    }
}

の結果:

Tom
Hello World

ここに画像の説明を挿入


この Kotlin クラスによって生成されたバイトコードの逆コンパイルされた Java コードを表示します。

import kotlin.Metadata;
import kotlin.jvm.internal.DefaultConstructorMarker;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 1,
   d1 = {
    
    "\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0003\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0004"},
   d2 = {
    
    "LHello;", "", "()V", "Companion", "KotlinDemo"}
)
public final class Hello {
    
    
   @NotNull
   private static String name = "Tom";
   public static final Hello.Companion Companion = new Hello.Companion((DefaultConstructorMarker)null);

   @Metadata(
      mv = {
    
    1, 1, 16},
      bv = {
    
    1, 0, 3},
      k = 1,
      d1 = {
    
    "\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0005\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\t\u001a\u00020\nR\u001a\u0010\u0003\u001a\u00020\u0004X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0005\u0010\u0006\"\u0004\b\u0007\u0010\b¨\u0006\u000b"},
      d2 = {
    
    "LHello$Companion;", "", "()V", "name", "", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "say", "", "KotlinDemo"}
   )
   public static final class Companion {
    
    
      @NotNull
      public final String getName() {
    
    
         return Hello.name;
      }

      public final void setName(@NotNull String var1) {
    
    
         Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
         Hello.name = var1;
      }

      public final void say() {
    
    
         String var1 = "Hello World";
         boolean var2 = false;
         System.out.println(var1);
      }

      private Companion() {
    
    
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
    
    
         this();
      }
   }
}

Kotlin でコンパイルされたバイトコード データでは、Hello.Companion コンパニオン オブジェクトに name メンバー属性と say メンバー関数が定義されているため、これら 2 つのメンバーにアクセスするには、Hello.Companion を介してアクセスする必要があります。


2. Java が Kotlin コンパニオン オブジェクトのメンバーに静的にアクセスする


次のコードでは、@JvmStatic アノテーションを使用して Kotlin のコンパニオン オブジェクトのメンバーを変更します。これらのメンバーは Java で静的にアクセスできます。


コトリンコード:

class Hello {
    
    
    companion object {
    
    
        @JvmStatic
        var name = "Tom"

        @JvmStatic
        fun say() {
    
    
            println("Hello World")
        }
    }
}

Java コード:

public class HelloJava {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(Hello.getName());
        Hello.say();
    }
}

の結果:
ここに画像の説明を挿入


この Kotlin クラスによって生成されたバイトコードの逆コンパイルされた Java コードを表示します。

import kotlin.Metadata;
import kotlin.jvm.JvmStatic;
import kotlin.jvm.internal.DefaultConstructorMarker;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {
    
    1, 1, 16},
   bv = {
    
    1, 0, 3},
   k = 1,
   d1 = {
    
    "\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0003\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0004"},
   d2 = {
    
    "LHello;", "", "()V", "Companion", "KotlinDemo"}
)
public final class Hello {
    
    
   @NotNull
   private static String name = "Tom";
   public static final Hello.Companion Companion = new Hello.Companion((DefaultConstructorMarker)null);

   @NotNull
   public static final String getName() {
    
    
      Hello.Companion var10000 = Companion;
      return name;
   }

   public static final void setName(@NotNull String var0) {
    
    
      Hello.Companion var10000 = Companion;
      name = var0;
   }

   @JvmStatic
   public static final void say() {
    
    
      Companion.say();
   }

   @Metadata(
      mv = {
    
    1, 1, 16},
      bv = {
    
    1, 0, 3},
      k = 1,
      d1 = {
    
    "\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0006\n\u0002\u0010\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\b\u0010\n\u001a\u00020\u000bH\u0007R$\u0010\u0003\u001a\u00020\u00048\u0006@\u0006X\u0087\u000e¢\u0006\u0014\n\u0000\u0012\u0004\b\u0005\u0010\u0002\u001a\u0004\b\u0006\u0010\u0007\"\u0004\b\b\u0010\t¨\u0006\f"},
      d2 = {
    
    "LHello$Companion;", "", "()V", "name", "", "name$annotations", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "say", "", "KotlinDemo"}
   )
   public static final class Companion {
    
    
      /** @deprecated */
      // $FF: synthetic method
      @JvmStatic
      public static void name$annotations() {
    
    
      }

      @NotNull
      public final String getName() {
    
    
         return Hello.name;
      }

      public final void setName(@NotNull String var1) {
    
    
         Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
         Hello.name = var1;
      }

      @JvmStatic
      public final void say() {
    
    
         String var1 = "Hello World";
         boolean var2 = false;
         System.out.println(var1);
      }

      private Companion() {
    
    
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
    
    
         this();
      }
   }
}

Kotlinクラスと、自動的に生成されます。

  • Hello.name 静的メンバーとその静的 Getter および Setter メソッド、
  • こんにちは、静的メソッドと言ってください。

これら 2 つの静的メンバーは、Kotlin クラスの Hello.Companion コンパニオン オブジェクトのメンバーですが、コンパイル中に Hello クラスで生成され、Hello クラスのメンバーと呼ばれます。

public final class Hello {
    
    
   @NotNull
   private static String name = "Tom";

   @NotNull
   public static final String getName() {
    
    
      Hello.Companion var10000 = Companion;
      return name;
   }

   public static final void setName(@NotNull String var0) {
    
    
      Hello.Companion var10000 = Companion;
      name = var0;
   }

   @JvmStatic
   public static final void say() {
    
    
      Companion.say();
   }
}

おすすめ

転載: blog.csdn.net/han1202012/article/details/129109314