2016-01-13 4 views
5

Gdybym dekompilować plik .class generowane przez data class State(val b: List<Array<Int>>) następnie pojawia się następujący kod Java:Pierwsze „niezgodne typy” błąd przy użyciu kodu wygenerowanego z Kotlin klasy danych

public final class State { 
    private final List<? extends Integer[]> b; 

    public State(List<? extends Integer[]> b) { 
     this.b = b; 
    } 

    public final List<Integer[]> getB() { 
     return this.b; 
    } 

    // ... 
} 

Gdybym kopiuj/wklej ten java kod do mojego IDE (IntelliJ 15), pojawia się następujący błąd kompilacji w metodzie getB():

Incompatible types. 

Required: List<Integer[]> 
Found: List<? extends Integer[]> 

Co ja tu brakuje? W jaki sposób kod wygenerowany przez Kotlin może to zrobić, ale nie moja kopia/wklejona wersja?

+0

Jakiej wersji Kotlin używasz? – nhaarman

Odpowiedz

12

Ogólnie, gdy javac ładuje plik .class, nie wykonuje pełnego sprawdzenia typu kodu w tej klasie; będzie ufać ogólnym sygnaturom określonym w bajtodzie. Z tego powodu inne języki JVM mogą generować sygnatury, których javac nie chciałby wygenerować.

W tym konkretnym przypadku symbole wieloznaczne generowane przez Kotlin beta 4 nie mają sensu (Integer[] jest klasą końcową, więc ? extends Integer[] jest bezużyteczna), więc bieżąca wersja rozwojowa nie generuje żadnych symboli wieloznacznych w tym przykładzie.

Generalnie naszym celem jest zapewnienie, że API napisane w Kotlin są łatwe do pobrania z kodu Java, a w celu osiągnięcia tego, Kotlin pozwala kontrolować, gdzie dokładnie generuje symbole wieloznaczne. Jest to opisane pod here pod "Java Wildcards".

+0

Świetna odpowiedź, dzięki! –