You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/topics/jvm/java-to-kotlin-interop.md
+81-28Lines changed: 81 additions & 28 deletions
Original file line number
Diff line number
Diff line change
@@ -10,9 +10,9 @@ On this page, we'll describe the ways to tailor the interop of your Kotlin code
10
10
11
11
A Kotlin property is compiled to the following Java elements:
12
12
13
-
* a getter method, with the name calculated by prepending the `get` prefix
14
-
* a setter method, with the name calculated by prepending the `set` prefix (only for `var` properties)
15
-
* a private field, with the same name as the property name (only for properties with backing fields)
13
+
* a getter method, with the name calculated by prepending the `get` prefix.
14
+
* a setter method, with the name calculated by prepending the `set` prefix (only for `var` properties).
15
+
* a private field, with the same name as the property name (only for properties with backing fields).
16
16
17
17
For example, `var firstName: String` compiles to the following Java declarations:
18
18
@@ -28,9 +28,9 @@ public void setFirstName(String firstName) {
28
28
}
29
29
```
30
30
31
-
If the name of the property starts with `is`, a different name mapping rule is used: the name of the getter will be
32
-
the same as the property name, and the name of the setter will be obtained by replacing `is` with `set`.
33
-
For example, for a property `isOpen`, the getter will be called `isOpen()` and the setter will be called `setOpen()`.
31
+
If the name of the property starts with `is`, a different name mapping rule is used: the name of the getter is
32
+
the same as the property name, and the name of the setter is obtained by replacing `is` with `set`.
33
+
For example, for a property `isOpen`, the getter is called `isOpen()` and the setter is called `setOpen()`.
34
34
This rule applies for properties of any type, not just `Boolean`.
35
35
36
36
## Package-level functions
@@ -109,7 +109,7 @@ org.example.Utils.getDate();
109
109
## Instance fields
110
110
111
111
If you need to expose a Kotlin property as a field in Java, annotate it with the [`@JvmField`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-field/index.html) annotation.
112
-
The field will have the same visibility as the underlying property. You can annotate a property with `@JvmField` if it:
112
+
The field has the same visibility as the underlying property. You can annotate a property with `@JvmField` if it:
113
113
* has a backing field
114
114
* is not private
115
115
* does not have `open`, `override` or `const` modifiers
@@ -132,14 +132,14 @@ class JavaClient {
132
132
```
133
133
134
134
[Late-Initialized](properties.md#late-initialized-properties-and-variables) properties are also exposed as fields.
135
-
The visibility of the field will be the same as the visibility of `lateinit` property setter.
135
+
The visibility of the field is the same as the visibility of the`lateinit` property setter.
136
136
137
137
## Static fields
138
138
139
-
Kotlin properties declared in a named object or a companion object will have static backing fields
139
+
Kotlin properties declared in a named object or a companion object have static backing fields
140
140
either in that named object or in the class containing the companion object.
141
141
142
-
Usually these fields are private but they can be exposed in one of the following ways:
142
+
Usually these fields are private, but they can be exposed in one of the following ways:
@@ -436,9 +436,8 @@ class Circle @JvmOverloads constructor(centerX: Int, centerY: Int, radius: Doubl
436
436
}
437
437
```
438
438
439
-
For every parameter with a default value, this will generate one additional overload, which has this parameter and
440
-
all parameters to the right of it in the parameter list removed. In this example, the following will be
441
-
generated:
439
+
For every parameter with a default value, this generates one additional overload, which has this parameter and
440
+
all parameters to the right of it in the parameter list removed. In this example, the following is generated:
442
441
443
442
```java
444
443
// Constructors:
@@ -452,7 +451,7 @@ void draw(String label) { }
452
451
```
453
452
454
453
Note that, as described in [Secondary constructors](classes.md#secondary-constructors), if a class has default
455
-
values for all constructor parameters, a public constructor with no arguments will be generated for it. This works even
454
+
values for all constructor parameters, a public constructor with no arguments is generated for it. This works even
456
455
if the `@JvmOverloads` annotation is not specified.
457
456
458
457
## Checked exceptions
@@ -586,3 +585,57 @@ fun emptyList(): List<Nothing> = listOf()
586
585
// is translated to
587
586
// List emptyList() { ... }
588
587
```
588
+
589
+
### Inline value classes
590
+
591
+
<primary-labelref="experimental-general"/>
592
+
593
+
If you want Java code to work smoothly with Kotlin's [inline value classes](inline-classes.md), you can use the
594
+
`@JvmExposeBoxed` annotation or the `-Xjvm-expose-boxed` compiler option. These approaches ensure Kotlin generates the
595
+
necessary boxed representations for Java interoperability.
596
+
597
+
By default, Kotlin compiles inline value classes to use **unboxed representations**, which are often inaccessible from Java.
598
+
For example, you can't call the constructor for the `MyInt` class from Java:
599
+
600
+
```kotlin
601
+
@JvmInline
602
+
value classMyInt(valvalue:Int)
603
+
```
604
+
605
+
So the following Java code fails:
606
+
607
+
```java
608
+
MyInt input =newMyInt(5);
609
+
```
610
+
611
+
You can use the [`@JvmExposeBoxed`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.jvm/-jvm-expose-boxed/) annotation so that Kotlin generates a public constructor that you can call from Java directly.
612
+
You can apply the annotation at the following levels to ensure fine-grained control over what's exposed to Java:
613
+
614
+
* Class
615
+
* Constructor
616
+
* Function
617
+
618
+
Before using the `@JvmExposeBoxed` annotation in your code, you must opt in by using `@OptIn(ExperimentalStdlibApi::class)`.
619
+
For example:
620
+
621
+
```kotlin
622
+
@OptIn(ExperimentalStdlibApi::class)
623
+
@JvmExposeBoxed
624
+
@JvmInline
625
+
value classMyInt(valvalue:Int)
626
+
627
+
@OptIn(ExperimentalStdlibApi::class)
628
+
@JvmExposeBoxed
629
+
fun MyInt.timesTwoBoxed(): MyInt=MyInt(this.value *2)
630
+
```
631
+
632
+
With these annotations, Kotlin generates a Java-accessible constructor for the `MyInt` class **and** a variant for the
633
+
extension function that uses the boxed form of the value class. So the following Java code runs successfully:
634
+
635
+
```java
636
+
MyInt input =newMyInt(5);
637
+
MyInt output =ExampleKt.timesTwoBoxed(input);
638
+
```
639
+
640
+
To apply this behavior to all inline value classes and the functions that use them within a module, compile it with the `-Xjvm-expose-boxed` option.
641
+
Compiling with this option has the same effect as if every declaration in the module has the `@JvmExposeBoxed` annotation.
0 commit comments