Kotlin-Generika für Java-Entwickler

Einige Kotlin-Generika können in Java ausgedrückt werden, andere nicht. Beginnen wir mit dem, was in Java ausgedrückt werden kann.

Generische Funktion

Lassen Sie uns eine generische Funktion in Kotlin deklarieren.

// Kotlin
fun <T> convertToString(arg: T) : String {
    return arg.toString()
}

Deklarieren Sie einen Typparameter zwischen dem Schlüsselwort fun in einer regulären Funktionsdeklaration und dem Funktionsnamen. Äquivalente Funktionen können in Java ausgedrückt werden.

// Java
<T> String convertToString(T arg) {
    return arg.toString();
}

Typeinschränkung

Sie können Typparameter einschränken.

fun <T: Exception> convertToString(arg: T) : String {
    return arg.localizedMessage
}

Der Typparameter T hat eine Einschränkung, die ihn zu einer Ausnahme oder seiner Unterklasse macht. Dies kann auch in Java ausgedrückt werden.

// Java
<T extends Exception> String convertToString(T arg) {
    return arg.getLocalizedMessage();
}

Generische Klasse

Definieren wir eine generische Klasse in Kotlin.

class Box<T>(t: T) {
    var value = t
}

Deklarieren Sie einen Typparameter zwischen dem Klassennamen und dem primären Konstruktor. Äquivalente Klassen können in Java dargestellt werden.

class Box<T> {
    T value;
    Box(T t) {
        this.value = t;
    }
}

Typeinschränkung

Sie können Typparameter für Klassen auch einschränken.

class Box<T: Number> (t: T) {
    var value = t
}

Der Typparameter T ist auf Number oder seine Unterklasse beschränkt. Dies kann auch in Java ausgedrückt werden.

static class Box<T extends Number> {
    T value;

    Box(T t) {
        this.value = t;
    }
}

where Klausel

Die "where" -Klausel ist nützlich, wenn Sie mehrere Typeinschränkungen in einer Funktion oder Klasse angeben möchten.

fun <T> doSomething(t: T) where T: Runnable, T: Cancellable {
    
}

Variable Deklaration und Verschiebungsspezifikation

Ähnlich wie beim Java-Boundary-Wildcard-Typ verfügt Kotlin auch über eine Notation, die die Verschiebung beim Deklarieren von Variablen angibt.

Java Kotlin
Obergrenze Einschränkung <? extends XXX> <out XXX>
Untergrenze Einschränkung <? super XXX> <in XXX>

Covariant

Hund ist ein Subtyp von Tier. Daher erstellt List \ eine kovariante Beziehung, sodass sie zu einem Subtyp von List \ wird.

open class Animal
class Dog: Animal()

var animals: List<out Animal> = emptyList()
val dogs: List<Dog> = emptyList()

animals = dogs

Rebellion

Hund ist ein Subtyp von Tier. List \ erstellt eine kontravariante Beziehung, sodass es sich um einen Subtyp von List \ handelt.

open class Animal
class Cat: Animal()

val animals: MutableList<Animal> = mutableListOf()
var cats: MutableList<in Cat> = mutableListOf()

cats = animals

In Kotlin wird die Verschiebungsspezifikation zum Zeitpunkt der Deklaration als ** Typprojektion ** bezeichnet.

Klassendeklaration und Verschiebungsspezifikation

In Java kann die Beziehung zwischen Kovariante und Kontravariante nicht in der Klasse selbst angegeben werden. Daher muss die Verschiebung jedes Mal angegeben werden, wenn die Variablendeklaration usw. erfolgt.

Kotlin hingegen verfügt über einen Mechanismus zum Festlegen der Verschiebung bei der Deklaration einer Klasse. Es besteht keine Gefahr, dass eine Verschiebung gegen die Absicht des Klassendesigners oder Implementierers verwendet wird.

//↓ Geben Sie die Position für den Typparameter an
class Supplier<out T> {
    fun get(): T {
        //
    }
}

Die Supplier-Klasse ist in Bezug auf den Typparameter T kovariant.

var animalSupplier: Supplier<Animal> = Supplier()
var dogSupplier: Supplier<Dog> = Supplier()
animalSupplier = dogSupplier

Es ist nicht erforderlich, die Verschiebung anzugeben, wenn die Variable deklariert wird. In ähnlicher Weise ist es möglich, eine Kontravariante durch Angabe der Position "in" zu erstellen.

Nicht null tolerant und generisch

Sie können den folgenden generischen Funktionen und Argumenten null übergeben.

fun <T> doSomething(t: T){
}

doSomething(null) // OK

Der Kotlin-Typ, der der Java-Stammklasse "Object" entspricht, ist "Any". Die Obergrenze für nicht eingeschränkte Typparameter lautet jedoch "Beliebig" anstelle von "Beliebig".

Wenn Sie eine nicht null tolerante generische Funktion deklarieren möchten Geben Sie "Beliebig" für die Typeinschränkung an.

fun <T: Any> doSomething(t: T){
}

doSomething(null) //Kompilierungsfehler
doSomething(1) // OK
doSomething("hoge") // OK

Sternprojektion

Es gibt einen Mechanismus namens Sternprojektion, der ein Sternchen "*" für den Typparameter angibt.

var animals: List<*> = //

Die obige "Liste <*>" ist nicht gleich "Liste <Beliebig?>". Es verhält sich wie "List <out Any?>". Die Sternprojektion ist eine Syntax, die verwendet wird, wenn Sie nicht an Typparametern interessiert sind. Es ist sicher, ein Element abzurufen und als "Beliebig?" Zu behandeln. Es ist jedoch nicht sicher, ein Element zu einer Liste hinzuzufügen.

Wie unten gezeigt, verhält es sich aufgrund des Risikos, einen unerwarteten Typ zu erhalten, wie eine "out" -Position.

val animals: MutableList<*> = mutableListOf<Animal>()
val animal = animals.first() // OK
animals.add(1) //Kompilierungsfehler
animals.add(Dog()) //Kompilierungsfehler

Recommended Posts

Kotlin-Generika für Java-Entwickler
Funktionen des Spring Frameworks für Java-Entwickler
Tipps zur Interoperabilität mit Kotlin zum Senden an Java-Entwickler
[Für Anfänger] Zusammenfassung des Java-Konstruktors
Kotlin-Klasse zum Senden an Java-Entwickler
[Java] Generika
Implementierung der Klonmethode für Java Record
Kotlins Klasse Teil 2 zum Senden an Java-Entwickler
Einführung in Kotlin für iOS-Entwickler lin ー Kotlin-Erstellung
Memo für die Migration von Java nach Kotlin
Java Generics Zusammenfassung
Für JAVA-Lernen (2018-03-16-01)
[Java] Generics-Beispiel
Java Generics (Hinweise)
2017 IDE für Java
[Java] Übersicht über Java
Java für Anweisung
Kotlin-Funktionen und Lambdas zum Senden an Java-Entwickler
Geben Sie Optionen für die Java / Kotlin-Kompilierungszeit für Android-Apps an
Zusammenfassung der Java-Umgebungseinstellungen für mich [mac]
Grundeinstellungen für das Umschreiben von Java-Projekten in Kotlin
Erste Schritte mit Kotlin zum Senden an Java-Entwickler
Hinweise zur Einführung für erfahrene JavaScript-Lernende von Java
Eine Sammlung einfacher Fragen für Java-Anfänger
Einführung in Kotlin für iOS-Entwickler ③-About gradle
Einführung in Kotlin für iOS-Entwickler ①-Umgebungskonstruktion
Einführung in Kotlin für iOS-Entwickler ②-Projekterstellung
[Einführung in Java] Grundlagen der Java-Arithmetik (für Anfänger)
[Java] für Anweisung, während Anweisung
Abgelaufene Java-Sammlung
Voraussichtliche Funktionen von Java
[Java] Bedeutung der serialVersionUID
Rufen Sie eine Liste mit MBean-Informationen für Java-Anwendungen ab
Bitte beachten Sie die Aufteilung (Aufteilung) von Java Kotlin Int und Int
[Java] Paket für die Verwaltung
[Für Anfänger] Verstehen Sie schnell die Grundlagen von Java 8 Lambda
NIO.2 Überprüfung von Java
Bewertung von Java Shilber
[Java] für Anweisung / erweitert für Anweisung
Initialisierung von for Versuchen Sie, das Java-Problem in TypeScript 5-4 zu ändern
Durchsuchen Sie Klassenobjekte in Kotlin (anstelle der Java-Klasse name.class).
Java - Vereinigung von Kommentaren
Häufig verwendete Java-Generika
Gegenmaßnahmen für OutOfMemoryError in Java
[Java, Kotlin] Typabweichung
Geschichte der Java-Annotationen
NLP für Java (NLP4J) (2)
(Memo) Java für Anweisung
NLP für Java (NLP4J) (1)
Einführung in Java für Anfänger Grundkenntnisse der Java-Sprache ①
Java Häufig verwendete Anweisungsliste (für Anfänger und Anfänger)
NIO Bewertung von Java
[Java] [Kotlin] Rufen Sie valueOf und Werte von Enum generisch auf
[Java10] Achten Sie darauf, var und generics nicht zusammen zu verwenden
[Java] Drei Funktionen von Java
Links für jede Version (japanische Version) der Java SE-API
[Null-Sicherheit] Kotlin Java-Vergleichsnotiz Richtige Verwendung der Null-Sicherheit
Ausführen des WebCamCapture-Beispiels von NyARToolkit für Java
Zusammenfassung der Java-Unterstützung 2018
Zusammenfassung der Methoden zum Lesen von Dateien für jedes Java-Dateiformat