为何Kotlin将协变类型参数转为不变型时会产生未检查转换警告?
为什么
Channel<out Message>转Channel<Message>会有未检查转换警告? 这个警告可不是无的放矢——看似安全的转换,其实藏着运行时崩溃的风险,核心原因在于协变投影类型的本质。
先明确:Channel<out Message>是一个协变投影,它代表的是“某个具体的Message子类的Channel实例”,但编译器不知道这个子类到底是什么。举个实际的例子:
假设你有TextMessage和ImageMessage两个Message的子类,实际代码里可能是这样的:
open class Message class TextMessage : Message() class ImageMessage : Message() // 实际是一个只能容纳TextMessage的Channel val textChannel: Channel<TextMessage> = Channel() // 通过协变投影,把它赋值给Channel<out Message>类型的变量 val outChannel: Channel<out Message> = textChannel
这时候outChannel的实际类型是Channel<TextMessage>,但编译期只知道它是“能产出Message的Channel”——也就是说,你只能从outChannel里读取元素(因为out修饰符限制了写入操作)。
但如果你强行把outChannel转成Channel<Message>,编译器就会解除写入限制:你可以调用send()方法往里面塞任何Message的子类,比如ImageMessage。可问题是,这个Channel的实际实例只能装TextMessage,往里面塞ImageMessage会直接触发运行时类型转换异常,完全不安全。
编译器之所以给出未检查转换警告,是因为它在编译期无法确认Channel<out Message>背后的实际类型到底是哪个子类的Channel。一旦你完成转换并执行写入操作,就可能引入致命的运行时错误。所以这个转换并非始终安全,警告是在提醒你要谨慎处理。
内容的提问来源于stack exchange,提问作者Archmede
相关产品推荐
相关产品推荐

