Kotlin.Collection vs. java.util.Collection


#1

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


#2

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?


#3

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


#4

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)


#5

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.


#6

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


#7

Why will there be a warning?

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


#8

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.