【问题标题】:What's the different of <reified T> with <reified T: Any> in Kotlin?Kotlin 中的 <reified T> 和 <reified T: Any> 有什么不同?
【发布时间】:2016-05-23 00:22:27
【问题描述】:

下面的测试类,通过。

class SimpleClassTest {

    private inline fun <reified T> anyObject(): T {
        return Mockito.anyObject<T>()
    }

    lateinit var simpleObject: SimpleClass
    @Mock lateinit var injectedObject: InjectedClass


    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    @Test
    fun testSimpleFunction() {
        simpleObject = SimpleClass(injectedObject)
        simpleObject.simpleFunction()

        verify(injectedObject).settingDependentObject(anyObject())
    }
}

但是如果我们改变

    private inline fun <reified T> anyObject(): T {
        return Mockito.anyObject<T>()
    }

    private inline fun <reified T: Any> anyObject(): T {
        return Mockito.anyObject<T>()
    }

它会失败

java.lang.IllegalStateException: Mockito.anyObject<T>() must not be null

&lt;reified T&gt;&lt;reified T: Any&gt; 在 Kotlin 中有什么不同?

更新 答案是 Any 是非空的,那么使用 &lt;reified T: Any&gt; 不应该返回错误,因为 settingDependentObject(...) 被声明接收非空参数。我希望&lt;reified T&gt; 应该出错,但这与我的理解相反。

我理解错了吗?

【问题讨论】:

标签: mockito kotlin


【解决方案1】:

作为stated in the documentationthe linked answer,默认上限为Any?。换句话说,以下声明是等价的:

inline fun <reified T> anyObject(): T = Mockito.anyObject<T>()
inline fun <reified T:Any?> anyObject(): T = Mockito.anyObject<T>()

Mockito.anyObject&lt;T&gt;() will return null 用于 T:AnyT:Any?。当调用返回类型为 T:Any 的方法时,Mockito 返回的 null 值无法通过 Kotlin 编译器插入的运行时检查。在调用 settingDependentObject 之前会抛出您遇到的错误。

【讨论】:

  • 谢谢 meinsol。当返回类型为 T:Any 的方法时?被调用,为什么 Mockito 返回的 null 值没有通过 Kotlin 编译器插入的运行时检查?
  • @Elye T:Any? 可以是null
  • 谢谢@miensol。现在明白了。如果您能回答,还有一个问题……我的settingDependentObject 函数也不接受空值。当T:任何?返回Null,为什么settingDependentObject不投诉?
  • @Eley 正如我在答案中提到的,IllegalStateException 在调用settingDependentObject 之前被抛出。当你有 settingDependentObject(anyObject())&lt;reified T:Any?&gt; anyObject() 因为 Any 匹配 T:Any? 时,编译器不会抱怨,反之亦然。
【解决方案2】:

当您在类型参数上添加 T : Any 约束时,您实际上是使其非空:TAny 的子类型,Any 不能包含空值。

由于函数是内联的并且有一个具体的类型参数,所以该参数被一个真正的不可为空的类型替换。因此在调用站点上执行空检查,所以你得到了这个异常。

【讨论】:

  • 谢谢莉亚。这有助于解释差异。我在更新中有一些后续问题,也许你可以解释一下?
猜你喜欢
  • 2020-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多