Kotlin.Collection vs. java.util.Collection

Hello,

I just realised that this doesn’t compile (using Kotlin 0.11.1014):

val coll: java.util.Collection<String> = java.util.ArrayList<String>()

I get this error:

Error:(14, 46) Kotlin: Type mismatch: inferred type is java.util.ArrayList<kotlin.String> but java.util.Collection<kotlin.String> was expected

It works when I do an explicit cast:

val coll: java.util.Collection<String> = java.util.ArrayList<String>() as java.util.Collection<String>

It is not clear to me whether this should work or whether I'm missing something. At least, I would expect this to work. It's not intuitive to me why I need to add the cast to java.util.Collection<String>. If someone could illuminate me on this.

Thanks, Oliver

The way it works curretly is that whenver we encounter a collection in Kotlin, we load a Kotlin version of this class (e.g. kotlin.Collection) instead of a Java version (java.util.*). Using the type java.util.Collection leads to a warning from the Kotlin compiler, because Kotlin's type checker is designed to distinguish between read-only and mutable collections. Why do you need to use java.util.Collection in your Kotlin code at all?

Problem is that f.ex. this does not compile:

val set = setOf(2, 5, 8) val result = set.filter { it > 2 } result.add(8) // Error:(13, 12) Kotlin: Unresolved reference: add

So I was looking for an alternative solution. By the way, this does not compile with the same error although toSet() is called:

val set = setOf(2, 5, 8) val result = set.filter { it > 2 }.toSet() result.add(8) // Error:(13, 12) Kotlin: Unresolved reference: add

Funny thing is that this prints "class java.util.ArrayList":

val set = setOf(2, 5, 8) val result = set.filter { it > 2 } println(result.javaClass)

Yet you can't call add on an  java.util.ArrayList ... Am using Kotlin 0.11.1079

Kotlin distinguished between read-only collections (subtypes of koltin.Collection) and mutable collections (subtypes of kotlin.MutableCollection). See blog post about Kotlin M3 for extra details (including built-in collection types).

setOf(), filter() and toSet() in context of your sample return read-only collections, so you can’t call add on them. If you need mutable collection, use toHashSet() or toArrayList() instead:

val set = setOf(2, 5, 8) val result = set.filter { it > 2 }.toHashSet() result.add(8)

If you need mutable collection, use toHashSet() or toArrayList() instead.

All right, I see. Once Kotlin turns 1.0 the news will spread and people will take Kotlin for a spin. Once they see that

val coll: java.util.Collection<String> = java.util.ArrayList<String>()

does not compile it will be considered weird, though.

It's not a big problem: they will get warning when using "java.util.Collection" anyway.

Why will there be a warning?

I thought the goal of Kotlin was to be highly interoperable with Java.

Kotlin is highly interoperable with Java. But there's no point in using some Java types (Collection, Integer etc) in Kotlin programs directly, hence the warning.