In short, default methods in interfaces in Kotlin are not compatible with Java.
That's the short version.
The long version follows.
Let's have a simple Person interface written in Kotlin:
Now we wish to use it in Java.
This doesn't work. Although the interface defines a default implementation of getGender(), this default implementation is invisible when called from Java.
Now, in the past there used to be something called @JvmDefault, but that is deprecated and doesn't work.
Instead it has been superseded by @JvmDefaultWithoutCompatibility1 and @JvmDefaultWithCompatibility2 (which, quite frankly, makes it a tad less understandable).
Also, when you use either annotation, you are required to add a command line parameter when you compile, or it won't work.
With compatibility requires -jvm-default=enable.
Without compatibility requires -jvm-default=no-compatibility.
However, it seems that the default is with compatibility that it is turned on automatically in Kotlin 2.2. Which will be released soonish hopefully.
How it works
Apparently what happens is that Kotlin automatically creates an Abstract class in the Interface that implements the methods that are default (under water). The abstract class is called Interface$DefaultImpls.
If you run Without Compatibility, it means that the DefaultImpls won't be generated but only "real Java default methods in the Interface". This means your interface in Kotlin will actually change (and is therefore not backwards compatible).
See reference [3] for more details.
References
- [1] Kotlin LangRef - JvmDefaultWithoutCompatibility
- https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.jvm/-jvm-default-without-compatibility/
- [2] Kotlin LangRef - JvmDefaultWithCompatibility
- https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.jvm/-jvm-default-with-compatibility/
- [3] KT-4779 Generate default methods for implementations in interfaces
- https://youtrack.jetbrains.com/issue/KT-4779/Generate-default-methods-for-implementations-in-interfaces