为何需将构造函数参数指定为可空泛型类型?
问题解答
为啥传null会报错?
你说的没错,Kotlin泛型T的默认上界确实是Any?,但这里的问题出在编译器对T的类型推导逻辑上:
当你调用无参的OK()方法时,编译器会尝试根据上下文推断T的具体类型。但你在方法里给构造函数传了null,而构造函数的data被声明为T——注意这里的T是非可空的占位符(因为你没给它加?)。这就会产生矛盾:
- 比如如果调用方把返回值赋值给
ApiResponse<Int>,那T就是Int(非空),null根本没法赋值给Int类型的参数,编译器肯定报错。 - 就算你没显式指定
T,编译器也不敢随便把T推导成Any?,因为T被声明为非可空的,它得保证这个类型在任何场景下都能满足非空要求。
改成T?为啥就好了?
把data改成T?之后,这个参数的类型就变成了可空泛型,不管T被推断成啥类型(比如Int或者String?),T?都能接受null:
- 要是
T是Int,T?就是Int?,自然能装null; - 要是
T本身就是String?,T?还是String?,同样能装null。
这样就彻底解决了类型不匹配的问题,因为null是所有可空类型的合法值。
额外:不想改data类型的话咋弄?
如果非要保持data为T(非可空),可以给无参OK()方法的泛型加个显式的可空约束:
fun <T : Any?> OK(): ApiResponse<T> { return ApiResponse(null, null) }
不过这种写法没啥必要,不如直接把data改成T?来得清晰。
内容的提问来源于stack exchange,提问作者lolo
相关产品推荐
相关产品推荐

