Collections.addAll don't know how to choose right method


#1

When i try to use Collections.addAll method like this:

val articleList1: MutableList<Article> = mutableListOf()
articleList1.addAll(articleList2) // articleList2's type is List<Article> define in java

Compiler complain that ’ type inference failed, please try to specify type arguments explicitly’, which means it use the method public fun <T> kotlin.collections.MutableCollection<in T>.addAll(elements: kotlin.collections.Iterable<T>): kotlin.Boolean in CollectionsKt.class.

But when i try to specify type for the function:

articleList1.addAll<Article>(articleList2) 

Wrong message is ‘No type arguments expected’, which means it use the method public abstract fun addAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean of MutableList class .

So, what can i do?


#2

Could you clarify, how do you declare the variable articleList2?


#3

Just List<Article> articleList2
This is an property in java bean.


#4

I wasn’t able to reproduce it with Kotlin 1.0.0. Here is what I’ve tried.

Articles.kt file:

class Article

fun useArticles(bean: ArticleBean) {
    val articleList1: MutableList<Article> = mutableListOf()
    articleList1.addAll(bean.articleList)
    articleList1.addAll<Article>(bean.articleList)
}

ArticleBean.java file:

import java.util.Collections;
import java.util.List;

public class ArticleBean {

    public List<Article> getArticleList() {
        return Collections.emptyList();
    }
}

Both the member addAll and the extension addAll are being resolved correctly.

Is there something different in your case?


#5

Yes, the only diffrent thing i guess is that my instance of ArticleBean is nullable.
And when i try use non-nullable references it works.


#6

So, can you reproduce this problem now?
Is there any good suggestion?


#7

So, you’re invoking its articleList property with a safe-call, like this?

    articleList1.addAll(bean?.articleList)
    articleList1.addAll<Article>(bean?.articleList)

In this case I do see a type mismatch error in both cases (it is reported on arguments), and errors you have mentioned in the first post on addAll.

The observed behavior is as it should be: addAll expects a List<T> as an argument, and you’re passing List<T>?, which is a result of a safe-call.

When you have a nullable variable of type List<T>? you can eliminate null either with the !! operator, or with the elvis-operator ?: or with the special extension function orEmpty defined for lists:

bean!!.articleList // throws NPE if bean is null
bean?.articleList!!  // throws NPE if bean is null or returned list is null
bean?.articleList.orEmpty()  // results in emptyList instead of null
bean?.articleList ?: emptyList()  // basically same as above

You can read more about null-safety in the docs:
https://kotlinlang.org/docs/reference/null-safety.html
https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types
and on StackOverflow:
In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them


#8

Thanks for your replies.
As your description i should provide a non-nullable argument for addAll, and i know how to do it.
But which mislead me is the compiler give me wrong information, which you & kotlin team should care for.