Generics 集合为nullable和not nullable的方法调用

Generics 集合为nullable和not nullable的方法调用,generics,kotlin,kotlin-null-safety,Generics,Kotlin,Kotlin Null Safety,在Kotlin中是否可以编写一个可以使用可空集合和不可空集合调用的函数?我会这样想: fun <C: MutableCollection<out String>> f(c: C): C { // ... } funf(c:c):c{ // ... } 我不需要这样写,因为我有一个C类型的返回值。还要注意out关键字,但即使使用它,我也不能调用f(mutableListOf),但是f(mutableListOf)工作正常。我必须在这里改变什么?在科特林这不可能吗

在Kotlin中是否可以编写一个可以使用可空集合和不可空集合调用的函数?我会这样想:

fun <C: MutableCollection<out String>> f(c: C): C {
    // ...
}
funf(c:c):c{
// ...
}
我不需要这样写,因为我有一个
C
类型的返回值。还要注意
out
关键字,但即使使用它,我也不能调用
f(mutableListOf)
,但是
f(mutableListOf)
工作正常。我必须在这里改变什么?在科特林这不可能吗?对于数组,这将很好地工作…

funf(c:c):c{
fun <C: MutableCollection<out String?>> f(c: C): C {
    return c;
}

fun main(args: Array<String>) {
    println(f(mutableListOf("hello")))
    println(f(mutableListOf<String?>(null)))
}
返回c; } 趣味主线(args:Array){ println(f(mutableListOf(“hello”))) println(f(mutableListOf(null))) }
funf(c:c):c{
返回c;
}
趣味主线(args:Array){
println(f(mutableListOf(“hello”)))
println(f(mutableListOf(null)))
}

我想你在这里把事情搞混了(参考你的评论)<代码>集合的工作方式与
数组
相同。在这种情况下,
T
可以通过任何方式(例如,
T:Any?
)。。。只要将
T
设置为
String
,基本上就是使用
C
,则必须使用不可为空的类型

简单的回答是,只需将
添加到泛型类型
C
,即使用
fun f(C:C):C
,以下是一些有助于更好地理解它们是如何协同工作的示例:

// your variant:
fun <C : MutableCollection<out String>> f1(c: C): C = TODO()
// given type must be non-nullable; returned one therefore contains too only non-nullable types

// your variant with just another generic type
fun <T : String, C : MutableCollection<out T>> f2(c: C): C = TODO()
// you have now your "out T", but it still accepts only non-nullable types (now it is probably just more visible as it is in front)

// previous variant adapted to allow nullable types:
fun <T : String?, C : MutableCollection<out T>> f3(c: C): C = TODO()
//您的变体:
乐趣f1(c:c):c=TODO()
//给定的类型必须是不可为空的;因此,返回的类型只包含不可为空的类型
//您的变体只是另一个泛型类型
乐趣f2(c:c):c=TODO()
//您现在有了“out T”,但它仍然只接受不可为null的类型(现在它可能只是比前面更可见)
//以前的变体适用于允许可为空的类型:
乐趣f3(c:c):c=TODO()
最后,您的问题的解决方案可以是以下之一(取决于您真正的需求):

funF4A(c:MutableCollection):MutableCollection=TODO()
乐趣f4b(c:c):c=TODO()

我想你在这里把事情搞混了(参考你的评论)<代码>集合的工作方式与
数组
相同。在这种情况下,
T
可以通过任何方式(例如,
T:Any?
)。。。只要将
T
设置为
String
,基本上就是使用
C
,则必须使用不可为空的类型

简单的回答是,只需将
添加到泛型类型
C
,即使用
fun f(C:C):C
,以下是一些有助于更好地理解它们是如何协同工作的示例:

// your variant:
fun <C : MutableCollection<out String>> f1(c: C): C = TODO()
// given type must be non-nullable; returned one therefore contains too only non-nullable types

// your variant with just another generic type
fun <T : String, C : MutableCollection<out T>> f2(c: C): C = TODO()
// you have now your "out T", but it still accepts only non-nullable types (now it is probably just more visible as it is in front)

// previous variant adapted to allow nullable types:
fun <T : String?, C : MutableCollection<out T>> f3(c: C): C = TODO()
//您的变体:
乐趣f1(c:c):c=TODO()
//给定的类型必须是不可为空的;因此,返回的类型只包含不可为空的类型
//您的变体只是另一个泛型类型
乐趣f2(c:c):c=TODO()
//您现在有了“out T”,但它仍然只接受不可为null的类型(现在它可能只是比前面更可见)
//以前的变体适用于允许可为空的类型:
乐趣f3(c:c):c=TODO()
最后,您的问题的解决方案可以是以下之一(取决于您真正的需求):

funF4A(c:MutableCollection):MutableCollection=TODO()
乐趣f4b(c:c):c=TODO()

谢谢,这很有效!你能解释一下为什么
在这里很重要吗?当使用数组
Array
和数组
Array
时,它不会编译,因为“类型参数的上限不能是数组”。这个这很重要,因为。。。您希望能够传递可空字符串的可变集合,而MutableCollection是不可空字符串的集合。@Cilenco:
out
非常粗略地表示“或子类型”。像
String?
这样的可空类型是其不可空基类型
String
的超类型。这就是为什么它需要
。谢谢你的帮助!你能解释一下为什么
在这里很重要吗?当使用数组
Array
和数组
Array
时,它不会编译,因为“类型参数的上限不能是数组”。这个这很重要,因为。。。您希望能够传递可空字符串的可变集合,而MutableCollection是不可空字符串的集合。@Cilenco:
out
非常粗略地表示“或子类型”。像
String?
这样的可空类型是其不可空基类型
String
的超类型。这就是为什么它需要