Как проверить, содержит ли список ноль в Kotlin? - PullRequest
0 голосов
/ 09 октября 2018

Мне трудно понять, почему

class Main {
    private val outputStreams: List<OutputStream>

    @JvmOverloads constructor(outputStreams: List<OutputStream> = LinkedList()) {
        if(outputStreams.contains(null)) {
            throw IllegalArgumentException("outputStreams mustn't contain null")
        }
        this.outputStreams = outputStreams
    }
}

вызывает ошибку компиляции ...Main.kt:[12,26] Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly..

Если я использую outputStreams.contains(null as OutputStream)), компиляция завершается успешно, но Main(LinkedList<OutputStream>()) не выполняется во время выполненияиз-за

kotlin.TypeCastException: null cannot be cast to non-null type java.io.OutputStream
    at kotlinn.collection.contains.nulll.check.Main.<init>(Main.kt:12)
    at kotlinn.collection.contains.nulll.check.MainTest.testInit(MainTest.kt:13)

, который оставляет меня без какого-либо другого подхода для сохранения кода как можно ближе к исходной Java, что является моим намерением, а также понимания этой проблемы в том виде, в каком она есть, вместо поиска обходного пути.

Ответы [ 4 ]

0 голосов
/ 17 января 2019

Метод filterNotNull () может отфильтровать все нулевые объекты из коллекции, чтобы вы могли использовать приведенный ниже код.Очевидно, что вам нужно сообщить компилятору, что объекты в коллекции могут быть обнуляемыми.Я изменил тип OutputStream на String для более простого тестирования.

    class Main{
private val outputStreams: List<String?>

@JvmOverloads constructor(outputStreams: List<String?> = LinkedList()) {

    if(outputStreams.filterNotNull().size < outputStreams.size) {
        throw IllegalArgumentException("outputStreams mustn't contain null")
    }
    this.outputStreams = outputStreams
}

fun getOutputStream(): List<String?>{
    return outputStreams
}
 }

Второй подход заключается в использовании let T.let (block: (T) -> R): R, где вы принимаете обнуляемый объект, но тогда вам придется проверить, есть ли какая-либо «нулевая» строка, и реагировать соответствующим образом.

    class Main{
lateinit var outputStreams: List<String?>

@JvmOverloads constructor(outputStreams: List<String?> = LinkedList()) {

    outputStreams.let {
        this.outputStreams = outputStreams
    }

}

fun getOutputStream(): List<String?>{
    return outputStreams
}
}

    fun main(args: Array<String>) {
val outputStreamWithNull: List<String?> = listOf("alpha", "beta", null, "omega")
val mainA = Main(outputStreamWithNull)


mainA.getOutputStream().forEach {
    println(it)
}

}

Если вы «уверены», что параметр объекта в конструкторе должен быть коллекцией ненулевыхобъекты, то вы можете удалить?Однако проверка на обнуляемость в коллекции List должна выполняться объектом, инициализирующим класс Main, так что в основном вы перекладываете ответственность за перехват NullPointerException на кого-то другого.

0 голосов
/ 09 октября 2018

Я верю, что ответ List<OutputStream?>.? сделает ваш список может содержать null.Проверьте документ: введите описание ссылки здесь

0 голосов
/ 09 октября 2018

У меня недостаточно представителей, чтобы комментировать ответ ToraCode, но в дополнение к тому, что они сказали, я ожидаю, что тип LinkedList() на самом деле List<OutputStream!>, что означает, что тип является либо List<OutputStream>, либо List<OutputStream?>

Типы с!после них типы платформ.Так что List<OutputStream!> будет означать, что «Java List of OutputStream может быть обнуляемым или нет». У нас просто нет возможности узнать.

Я думаю, что наиболее безопасно следовать рекомендациям ToraCode, использовать List<OutputStream?> и проверять наличие нулей.

Для получения дополнительной информации о совместимости kotlin см .: https://kotlinlang.org/docs/reference/java-interop.html#notation-for-platform-types

0 голосов
/ 09 октября 2018

Для компилятора параметр outputStreams не может содержать null, поскольку его тип равен List<OutputStream>, а не List<OutputStream?>.Система типов не ожидает, что null будет внутри этого списка, поэтому нет необходимости проверять его.

С другой стороны * , ЕСЛИ этот параметр на самом деле может содержать null (так как он исходит от вызывающей стороны Java), вы должны явно пометить его как обнуляемый: List<OutputStream?>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...