2016-05-23 5 views
5

Die Testklasse unten, bestanden.Was ist der Unterschied von <reified T> mit <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()) 
    } 
} 

Aber wenn wir von

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

zu

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

Es mit

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

fehl ändern, was die verschiedenen von <reified T> mit <reified T: Any> in Kotlin ist?

AKTUALISIERT Mit der Antwort, dass jeder Nicht-Null ist, dann <reified T: Any> verwenden, sollten Fehler nicht zurück, da settingDependentObject(...) erklärt ein nicht-Null-Argument zu empfangen. Ich würde erwarten, <reified T> sollte stattdessen Fehler aus, aber es ist das Gegenteil von dem, was ich verstehe.

Habe ich etwas falsch verstanden?

+1

Mögliche Duplikate von [Kotlin: Generics, Reflexion und der Unterschied zwischen Typ T und T: Beliebige] (http://stackoverflow.com/questions/35602231/kotlin-generics-reflection-and-the-difference-between- type-t-and-tany) – hotkey

+1

Mockito.anyObject ist eine Java-Methode und gibt Platform-Type "Any!" Dieser Typ kann null- oder nullfähig sein. Der Kotlin-Compiler wird dort nichts ableiten (weil Null-Checks für jeden Plattform-Typ laut sind). Wenn du also "Any!" Bei einem "Any" kann dies zur Laufzeit fehlschlagen. siehe: https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types – D3xter

Antwort

7

Als stated in the documentation und the linked answer ist die Standardobergrenze Any?. Mit anderen Worten sind die folgenden Erklärungen äquivalent:

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

Die Mockito.anyObject<T>()will return null sowohl für T:Any und T:Any?. Wenn die Methode mit dem Rückgabetyp T:Any aufgerufen wird, schlägt der von Mockito zurückgegebene Wert null die Laufzeitprüfung fehl, die vom Kotlin-Compiler eingefügt wurde. Der Fehler, den Sie erhalten, wird ausgelöst, bevor settingDependentObject aufgerufen wird.

+0

Danke meinsol. Wenn die Methode mit Rückgabetyp T: Beliebig? Wird aufgerufen, warum nicht der von Mockito zurückgegebene Nullwert die vom Kotlin-Compiler eingefügte Laufzeitprüfung nicht besteht? – Elye

+0

@Elye 'T: Any?' Kann 'null' sein – miensol

+0

Danke @miensol. Jetzt verstanden. Eine weitere Frage, wenn Sie antworten könnten ... meine 'settingDependentObject' Funktion akzeptiert auch keine Null. Wann T: Irgendwelche? gibt Null zurück, warum nicht "settingDependentObject" Beschwerden? – Elye

3

Wenn Sie T : Any Einschränkung für einen Typ-Parameter hinzufügen, werden Sie es effektiv nicht-null zu machen: T Subtyp von Any und Any sind nulls nicht halten kann.

Da die Funktion inline ist und einen verdienten Typparameter hat, wird dieser Parameter durch einen reellen, nicht nullbaren Typ ersetzt. Und deshalb wird auf einer Aufrufseite eine Nullprüfung durchgeführt, daher erhalten Sie diese Ausnahme.

+0

Danke llya. Das erklärt die Unterschiede. Ich habe einige Nachfragen im Update, vielleicht könntest du es erklären? – Elye