[Kotlin] Interoperabilidad entre Kotlin y Java② (campo de anotación @JvmField para Java | Función de modificación de anotación @JvmOverloads | La anotación @JvmStatic declara miembros estáticos)





1. Use la anotación @JvmField para exponer los campos de Kotlin a Java




1. Acceda a los campos de Kotlin a través de los métodos Getter y Setter en las clases de Java


No se puede acceder a los campos en Kotlin directamente en Java , y se debe llamar a los métodos Getter y Setter correspondientes para acceder;


Ejemplo de código:


Clase Kotlin: las propiedades de miembro declaradas en Kotlin son propiedades privadas privadas de forma predeterminada, y los métodos Getter y Setter se generan para ellas de forma predeterminada;

class Hello {
    
    
    var name = "Tom"
}

Llamadas directas desde clases de Java: en las clases de Java, los campos de Kotlin no se pueden llamar directamente;

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

Se informará un error en la clase Java:

'name' has private access in 'Hello'

inserte la descripción de la imagen aquí


En las clases de Java, los campos de Kotlin solo se pueden llamar a través de los métodos Getter y Setter ;

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

Resultados de la :
inserte la descripción de la imagen aquí


2. Acceso directo a campos Kotlin decorados con anotaciones @JvmField en clases Java


Si usa la anotación @JvmField para modificar las propiedades de los miembros en Kotlin , su función es exponer los campos de Kotlin a Java , y puede acceder directamente a los campos de Kotlin en Java sin ;


codigo kotlin:

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

Código Java:

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

Resultados de la :

inserte la descripción de la imagen aquí

La anotación @JvmField es equivalente a declarar un campo en Kotlin como un campo de Java , momento en el que Kotlin no generará automáticamente métodos Getter y Setter para el campo;





2. Use la anotación @JvmOverloads para modificar la función Kotlin



En Kotlin, los parámetros de función pueden tener sus propios valores predeterminados , y puede pasar directamente ;

Sin embargo, cuando Java llama a las funciones de Kotlin , el lenguaje Java no admite la sintaxis de los parámetros de función con valores predeterminados.Si se pasan los parámetros especificados, la función debe sobrecargarse;

El uso de la anotación @JvmOverloads para modificar la función Kotlin en Kotlin implementará automáticamente una serie de funciones sobrecargadas para los usuarios de Java;
por ejemplo, si la lista de parámetros es ( String , edad ), el uso de la anotación @JvmOverloads para modificar la función generará automáticamente

  • 0 parámetros,
  • 1 parámetro,
  • 2 parámetros

La función ;


1. Ejemplo de llamada de función de parámetro predeterminado de Kotlin


Ejemplo de código de Kotlin: en la siguiente helloStudentfunción , ambos parámetros se establecen con valores de parámetro predeterminados . Al llamar a esta función en Kotlin, puede pasar 0, 1 y 2 parámetros , y puede elegir qué parámetro pasar si pasa un parámetro;

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)
}

Resultados de la :

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 !

inserte la descripción de la imagen aquí

Analice los datos de bytecode del código Kotlin anterior , vea los datos de bytecode en Kotlin Bytecode y descompílelos en código Java de la siguiente manera:

// 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. Llame a la función de parámetro predeterminado de Kotlin en Java


Si desea pasar cualquier número y tipo de parámetros en código Java como Kotlin, debe usar la sobrecarga de funciones;

Si se llama directamente como en Kotlin, definitivamente se informará un error:
inserte la descripción de la imagen aquí

El uso de la anotación @JvmOverloads para modificar la función de Kotlin implementará automáticamente una serie de funciones sobrecargadas para los usuarios de Java;


Ejemplo de código 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)
}

Ejemplo de código Java:

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

Resultados de la :

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

inserte la descripción de la imagen aquí

Analice los datos de bytecode anteriores correspondientes a la clase de Kotlin anotados con @JvmOverloads y descompile el bytecode de nuevo al código Java, el contenido es el siguiente:

// 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();
   }
}

Después de usar la anotación @JvmOverloads , las funciones sobrecargadas con parámetros 0, 1 y 2 se generan automáticamente para la función helloStudent
en tiempo de compilación , de modo que estos métodos se pueden llamar directamente cuando se los llama en 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. Use la anotación @JvmStatic para declarar miembros estáticos



En Kotlin, no existe el concepto de miembros estáticos.Cuando se necesita declarar un miembro estático , generalmente se declara en su objeto complementario Companion;

Al llamar a miembros en el objeto complementario Kotlin's Companion en Java , debe llamar de la siguiente forma:

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

Si desea llamar directamente a los miembros del objeto complementario Companion en Kotlin sin usar Companion ,

Puede estar en el objeto complementario ,

Use la anotación @JvmStatic para declarar miembros en el objeto complementario como miembros estáticos de Java,

En Java, se puede acceder a él como miembro estático;


1. Java normalmente accede a los miembros de objetos complementarios de Kotlin


En el siguiente código, para acceder a los miembros del objeto complementario de Kotlin en el lenguaje Java, primero debe obtener el objeto complementario de la clase Hello.Companion y luego acceder a los miembros del objeto complementario;


codigo kotlin:

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

Código Java:

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

Resultados de la :

Tom
Hello World

inserte la descripción de la imagen aquí


Vea el código Java descompilado del bytecode generado por esta clase de Kotlin:

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();
      }
   }
}

En los datos de código de bytes compilados por Kotlin, el atributo de miembro de nombre y la función de miembro de decir se definen en el objeto complementario Hello.Companion Si desea acceder a estos dos miembros, debe acceder a ellos a través de Hello.Companion;


2. Java accede estáticamente a los miembros de objetos complementarios de Kotlin


En el siguiente código, use la anotación @JvmStatic para modificar los miembros del objeto complementario en Kotlin, y luego se podrá acceder a estos miembros de forma estática en Java;


codigo kotlin:

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

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

Código Java:

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

Resultados de la :
inserte la descripción de la imagen aquí


Vea el código Java descompilado del bytecode generado por esta clase de Kotlin:

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();
      }
   }
}

Cuando se compila la , se genera automáticamente

  • Miembro estático Hello.name y sus métodos Getter y Setter estáticos,
  • Hola, di método estático;

Estos dos miembros estáticos son miembros del objeto complementario Hello.Companion en la clase Kotlin, pero se generan en la clase Hello durante la compilación y se denominan miembros de la clase 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();
   }
}

Supongo que te gusta

Origin blog.csdn.net/han1202012/article/details/129109314
Recomendado
Clasificación