Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the different of <reified T> with <reified T: Any> in Kotlin?

Tags:

mockito

kotlin

The test class below, pass.

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())
    }
}

But if we change from

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

to

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

It will fail with

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

What's the different of <reified T> with <reified T: Any> in Kotlin?

UPDATED With the answer that Any is non-null, then using <reified T: Any> shouldn't return error, since settingDependentObject(...) is declared receiving a non-null argument. I would expect <reified T> should error out instead, but it's opposite from what I understand.

Did I understand something wrong?

like image 488
Elye Avatar asked May 23 '16 00:05

Elye


2 Answers

As stated in the documentation and the linked answer the default upper bound is Any?. In other words the following declarations are equivalent:

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

The Mockito.anyObject<T>() will return null for both T:Any and T:Any?. When the method with return type T:Any is invoked the null value returned by Mockito fails the runtime check inserted by Kotlin compiler. The error you're getting is thrown before settingDependentObject is invoked.

like image 127
miensol Avatar answered Dec 17 '22 07:12

miensol


When you add T : Any constraint on a type parameter, you're making it effectively non-null: T is subtype of Any and Any can't hold nulls.

Since the function is inline and has a reified type parameter, that parameter gets substituted with a real non-nullable type. And thus a null-check is performed on a call site, so you're getting this exception.

like image 43
Ilya Avatar answered Dec 17 '22 06:12

Ilya