Search code examples
javakotlingenericscollectionscovariance

Error in implementing Kotlin interface with Java: incompatible return type


I try to implement a Kotlin interface in Java, so my interface looks like this:

interface KInterface {
    val items: Collection<ItemInterface>
}

interface ItemInterface {
//
}

Then, in my Java code I have the following classes:

class JavaItemImpl implemets ItemInterface {
//
}

class JavaImpl implements KInterface {
    private List<JavaItemImpl> items;
    
    @Override
    public List<? extends ItemInterface> getItems() {
        return items;
    }
}

Kotlin Collection is covariant public interface Collection<out E> : Iterable<E>, so I assume that List<? extends ItemInterface> would work when implementing a Kotlin interface. However, this code gives me an error: 'getItems()' in 'JavaImpl' clashes with 'getItems()' in 'KInterface'; attempting to use incompatible return type.

One workaround is to make items in KInterface mutable collection and add a type projection, like this:

    val items: MutableCollection<out ItemInterface>

But I'd like to know, is there any other way to implement such Kotlin interface, without making Kotlin collection mutable?


Solution

  • Apply @JvmWildcard to the type parameter of Collection:

    interface KInterface {
        val items: Collection<@JvmWildcard ItemInterface>
    }
    

    Then the implementation can return java.util.Collection<? extends ItemInterface> (or narrow to List, as you have):

    @Override @NotNull public Collection<? extends ItemInterface> getItems() {
        return items;
    }