Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement this Java interface in Kotlin?

Since Kotlin doesn't have primitives, how could this interface be implemented?

public interface A {   @NotNull Object get(@NotNull Integer i);   @NotNull Object get(int i); } 

I cannot change the Java code since it's a compiled class file in a binary library.

like image 493
ice1000 Avatar asked May 23 '17 10:05

ice1000


Video Answer


2 Answers

If a single implementation, as in @zsmb13's answer, is not enough for you and you need separate implementations for the two methods in Kotlin, then you can add an intermediate interface overriding the method accepting Integer with a nullable parameter:

private interface IntermediateA : A {     override fun get(i: Int?): Any } 

Implementing this interface instead of the original A, the Kotlin compiler will distinguish the two methods, allowing you to override them as follows:

class C : IntermediateA {     override fun get(i: Int) = "primitive"     override fun get(i: Int?) = "boxed" } 

val a: A = C() println(a.get(1)) // primitive println(a.get(1 as Int?)) // boxed 

If you had access to the Java code, you could fix this by adding a nullability annotation to the method accepting the boxed type:

Object get(@Nullable Integer i); 

The Kotlin compiler understands different kinds of nullability annotations, here's the list.

like image 112
hotkey Avatar answered Sep 25 '22 10:09

hotkey


Implementing just one method that takes Int as its parameter works, and can be called from either Kotlin or Java.

class B : A {      override fun get(i: Int): Any {         return "something"     }  } 

If you decompile the bytecode, you'll see that the Kotlin compiler is smart enough to create both methods, with one of them just redirecting to the real implementation.

Decompiled bytecode example

One possible problem is that you can't make the method take Int?, and it will crash with a NullPointerException on the .intValue() call if it's called from Java like so:

B b = new B(); Integer i = null; b.get(i); 

I'm not sure if there's a way to solve for that use case.

Edit: hotkey's answer has rest of the answers in it.

like image 29
zsmb13 Avatar answered Sep 26 '22 10:09

zsmb13