2016-05-23 25 views
5

La classe di test di seguito, passaggio.Qual è la differenza di <reified T> con <reified T: Any> in Kotlin?

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

Ma se ci si sposta dall'attuale

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

a

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

fallirà con

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

Qual è il diverso di <reified T> con <reified T: Any> in Kotlin?

AGGIORNATO Con la risposta che Any non è nullo, quindi utilizzando <reified T: Any> non dovrebbe restituire l'errore, dal momento che settingDependentObject(...) viene dichiarata la ricezione di un argomento non nullo. Mi aspetterei che l'errore <reified T> si verifichi invece, ma è opposto a quello che ho capito.

Ho capito qualcosa di sbagliato?

+1

Possibile duplicato di [Kotlin: Generics, reflection e la differenza tra type T e T: Any] (http://stackoverflow.com/questions/35602231/kotlin-generics-reflection-and-the-difference-between- type-t-and-tany) – hotkey

+1

Mockito.anyObject è un metodo java e restituisce Platform-Type "Any!" Quel tipo può essere nullable o non annullabile. il compilatore kotlin non dedurrà nulla lì (perché avere controlli nulli per ogni tipo di piattaforma è rumoroso). quindi se assegni "Qualsiasi!" a un "Qualsiasi", questo può fallire in fase di runtime. vedere: https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types – D3xter

risposta

7

Come stated in the documentation e the linked answer il limite superiore predefinito è Any?. In altre parole le seguenti dichiarazioni sono equivalenti:

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

Il Mockito.anyObject<T>()will return null sia T:Any e T:Any?. Quando viene richiamato il metodo con tipo di ritorno T:Any, il valore null restituito da Mockito non supera il controllo di runtime inserito dal compilatore Kotlin. L'errore che stai ricevendo viene lanciato prima che venga invocato lo settingDependentObject.

+0

Grazie a meinsol. Quando il metodo con tipo di ritorno T: Qualsiasi? viene invocato, perché il valore nullo restituito da Mockito non ha esito negativo sul controllo runtime inserito dal compilatore Kotlin? – Elye

+0

@Elye 'T: Any?' Può essere 'null' – miensol

+0

Grazie a @miensol. Capito ora. Un'ulteriore domanda se potessi rispondere ... anche la mia funzione 'settingDependentObject' non accetta null. Quando T: Any? restituisce Null, perché non 'reclami' settingDependentObject'? – Elye

3

Quando si aggiunge T : Any vincolo su un parametro di tipo, si sta facendo in modo efficace non nullo: T è sottotipo di Any e Any non può tenere i null.

Poiché la funzione è in linea e ha un parametro di tipo reificato, tale parametro viene sostituito con un tipo reale non annullabile. E quindi viene eseguito un controllo nullo su un sito di chiamata, quindi stai ricevendo questa eccezione.

+0

Grazie llya. Questo aiuta a spiegare le differenze. Ho qualche domanda da seguire nell'aggiornamento, forse potresti spiegarci? – Elye