Article directory
1. Use the @JvmField annotation to expose Kotlin fields to Java
1. Access Kotlin fields through Getter and Setter methods in Java classes
Fields in Kotlin cannot be accessed directly in Java , and the corresponding Getter and Setter methods must be called to access;
Code example:
Kotlin class: The member properties declared in Kotlin are private private properties by default, and Getter and Setter methods are generated for them by default;
class Hello {
var name = "Tom"
}
Direct calls from Java classes: In Java classes, Kotlin fields cannot be called directly;
public class HelloJava {
public static void main(String[] args) {
Hello hello = new Hello();
System.out.println(hello.name);
}
}
An error will be reported in the Java class:
'name' has private access in 'Hello'
In Java classes, Kotlin fields can only be called through Getter and Setter methods ;
public class HelloJava {
public static void main(String[] args) {
Hello hello = new Hello();
System.out.println(hello.getName());
}
}
Results of the :
2. Direct access to Kotlin fields decorated with @JvmField annotations in Java classes
If you use the @JvmField annotation to modify member properties in Kotlin , its function is to expose Kotlin fields to Java , and you can directly access Kotlin fields in Java without ;
Kotlin code:
class Hello {
@JvmField
var name = "Tom"
}
Java code:
public class HelloJava {
public static void main(String[] args) {
Hello hello = new Hello();
System.out.println(hello.name);
}
}
Results of the :
The @JvmField annotation is equivalent to declaring a field in Kotlin as a Java field , at which point Kotlin will not automatically generate Getter and Setter methods for the field;
2. Use the @JvmOverloads annotation to modify the Kotlin function
In Kotlin, function parameters can have their own default values , and you can directly ;
However, when Java calls Kotlin functions , the Java language does not support the syntax of function parameters with default values . If the specified parameters are passed in, the function needs to be overloaded;
Using the @JvmOverloads annotation to modify the Kotlin function in Kotlin will automatically implement a series of overloaded functions for Java users;
for example, if the parameter list is ( String , age ), using the @JvmOverloads annotation to modify the function will automatically generate
- 0 parameters,
- 1 parameter,
- 2 parameters
The function ;
1. Kotlin default parameter function call example
Kotlin code example: In the following helloStudent
function , both parameters are set with default parameter values . When calling this function in Kotlin, you can pass in 0, 1, and 2 parameters , and you can choose which parameter to pass in if you pass in one parameter ;
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)
}
Results of the :
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 !
Analyze the bytecode data of the above Kotlin code , view the bytecode data in Kotlin Bytecode, and decompile it into Java code as follows:
// 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. Call Kotlin default parameter function in Java
If you want to pass in any number and type of parameters in Java code like Kotlin, you need to use function overloading;
If it is called directly like in Kotlin, an error will definitely be reported:
Using the @JvmOverloads annotation to modify the Kotlin function will automatically implement a series of overloaded functions for Java users;
Kotlin code example:
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 code example:
public class HelloJava {
public static void main(String[] args) {
Hello hello = new Hello();
hello.helloStudent();
hello.helloStudent("Jerry");
hello.helloStudent("Bill", 12);
}
}
Results of the :
Student Tom is 18 years old , say hello !
Student Jerry is 18 years old , say hello !
Student Bill is 12 years old , say hello !
Analyze the above bytecode data corresponding to the Kotlin class annotated with @JvmOverloads , and decompile the bytecode back to Java code, the content is as follows:
// 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();
}
}
After using the @JvmOverloads annotation , overloaded functions with 0, 1, and 2 parameters are automatically generated for the helloStudent function
at compile time , so that these methods can be called directly when called in 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 the @JvmStatic annotation to declare static members
In Kotlin, there is no concept of static members . When a static member needs to be declared , it is generally declared in its Companion companion object;
When calling members in Kotlin's Companion companion object in Java , you need to call in the following form:
Kotlin类.Companion.成员属性
Kotlin类.Companion.成员函数
If you want to directly call Companion companion object members in Kotlin without using Companion ,
Can be in companion object ,
Use the @JvmStatic annotation to declare members in the companion object as Java static members,
In Java, it can be accessed as a static member;
1. Java normally accesses Kotlin companion object members
In the following code, to access the members of the Kotlin companion object in the Java language, you need to obtain the companion object of the Hello.Companion class first, and then access the members of the companion object;
Kotlin code:
class Hello {
companion object {
var name = "Tom"
fun say() {
println("Hello World")
}
}
}
Java code:
public class HelloJava {
public static void main(String[] args) {
System.out.println(Hello.Companion.getName());
Hello.Companion.say();
}
}
Results of the :
Tom
Hello World
View the decompiled Java code of the bytecode generated by this Kotlin class:
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();
}
}
}
In the bytecode data compiled by Kotlin, the name member attribute and the say member function are defined in the Hello.Companion companion object. If you want to access these two members, you must access them through Hello.Companion;
2. Java statically accesses Kotlin companion object members
In the following code, use the @JvmStatic annotation to modify the members of the companion object in Kotlin, and then these members can be accessed statically in Java;
Kotlin code:
class Hello {
companion object {
@JvmStatic
var name = "Tom"
@JvmStatic
fun say() {
println("Hello World")
}
}
}
Java code:
public class HelloJava {
public static void main(String[] args) {
System.out.println(Hello.getName());
Hello.say();
}
}
Results of the :
View the decompiled Java code of the bytecode generated by this Kotlin class:
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();
}
}
}
When the Kotlin class is compiled , it is automatically generated
- Hello.name static member and its static Getter and Setter methods,
- Hello. say static method;
These two static members are members of the Hello.Companion companion object in the Kotlin class, but they are generated in the Hello class during compilation and are called members of the Hello class;
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();
}
}