我无法理解为什么
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,这是我的意图,同时也是要真正理解此问题,而不是寻找解决方法。
答案 0 :(得分:4)
对于编译器,参数outputStreams
不能包含null
,因为其类型为List<OutputStream>
,而不是List<OutputStream?>
。类型系统不希望null
包含在此列表中,因此无需检查它。
另一方面,如果该参数实际上可能包含null
(由于它来自Java调用程序),则应将其明确标记为可为空: List<OutputStream?>
答案 1 :(得分:3)
我相信答案是List<OutputStream?>
。 ?
将使您的列表可以包含null
。
检查文档:enter link description here
答案 2 :(得分:1)
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)
}
}
如果您“确信”构造函数中的object参数应该是非null对象的集合,则可以删除? 但是,必须通过初始化Main类的对象来完成对List集合的可空检查,因此您基本上会将捕获NullPointerException的职责转移给其他人。
答案 3 :(得分:0)
我没有足够的代表评论ToraCode的答案,但按照他们所说的,我希望LinkedList()
的类型实际上是List<OutputStream!>
,这意味着该类型可以是{{1 }}或List<OutputStream>
带有!的类型它们是平台类型。因此List<OutputStream?>
的意思是“ OutputStream的Java列表可能为空或不能为空”。我们根本无法知道。
我认为遵循ToraCode的建议,使用List<OutputStream!>
并检查是否为空是最安全的。
有关kotlin互操作性的更多信息,请参见:https://kotlinlang.org/docs/reference/java-interop.html#notation-for-platform-types