Generics of Kotlin for Java developers

Some Kotlin generics can be expressed in Java, while others are not. Let's start with what can be expressed in Java.

Generic function

Let's declare a generic function in Kotlin.

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

Declare a type parameter between the fun keyword in a normal function declaration and the function name. Equivalent functions can be expressed in Java.

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

Type constraint

You can constrain type parameters.

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

The type parameter T has a constraint that makes it an Exception or its subclass. This can also be expressed in Java.

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

Generic class

Let's define a generic class in Kotlin.

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

Declare a type parameter between the class name and the primary constructor. The equivalent class can be expressed in Java.

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

Type constraint

You can also constrain type parameters for classes.

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

The type parameter T is constrained to be Number or its subclass. This can also be expressed in Java.

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

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

where clause

The where clause is useful when you want to specify multiple type constraints in a function or class.

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

Variable declaration and displacement specification

Similar to Java's boundary wildcard type, Kotlin also has a notation for specifying displacement when declaring variables.

Java Kotlin
Upper bound constraint <? extends XXX> <out XXX>
Lower bound constraint <? super XXX> <in XXX>

Covariant

Dog is a subtype of Animal. Therefore, List \ creates a covariant relationship so that it becomes a subtype of List \ .

open class Animal
class Dog: Animal()

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

animals = dogs

Rebellion

Dog is a subtype of Animal. List \ creates a contravariant relationship so that it is a subtype of List \ .

open class Animal
class Cat: Animal()

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

cats = animals

In Kotlin, the displacement specification at the time of declaration is called ** type projection **.

Class declaration and displacement specification

In Java, the relationship between covariant and contravariant cannot be specified in the class itself. Therefore, it is necessary to specify the displacement each time the variable declaration etc.

Kotlin, on the other hand, has a mechanism for specifying displacement when declaring a class. There is no risk of displacement being used against the intent of the class designer or implementer.

//↓ Specify out position for type parameter
class Supplier<out T> {
    fun get(): T {
        //
    }
}

The Supplier class is covariant with respect to the type parameter T.

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

Displacement specification is not required when declaring a variable. Similarly, it is possible to make a contravariant by specifying the ʻin` position.

Non-nullable and generic

You can pass null to the following generic functions and arguments.

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

doSomething(null) // OK

The Kotlin type that corresponds to the Java root class ʻObject is ʻAny. However, the upper bound for unconstrained type parameters is ʻAny? Instead of ʻAny.

If you want to declare a non-nullable generic function Specify ʻAny` for the type constraint.

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

doSomething(null) //Compile error
doSomething(1) // OK
doSomething("hoge") // OK

Star projection

There is a mechanism called star projection that specifies an asterisk * for the type parameter.

var animals: List<*> = //

The above List <*> is not equal to List <Any?>. It behaves as List <out Any?>. Star projection is a syntax used when you are not interested in type parameters. It's safe to take an element and treat it as ʻAny?`, But adding an element to a list is not safe.

As shown below, it behaves as a ʻout` position due to the risk of receiving an unexpected type.

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

Recommended Posts

Generics of Kotlin for Java developers
Features of spring framework for java developers
Interoperability tips with Kotlin for Java developers
[Java] Summary of for statements
[For beginners] Summary of java constructor
Kotlin Class to send to Java developers
[Java] Generics
Implementation of clone method for Java Record
Kotlin Class part.2 to send to Java developers
Introduction to kotlin for iOS developers ⑥-Kotlin creation
Memo for migration from java to kotlin
Java Generics Summary
For JAVA learning (2018-03-16-01)
[Java] Generics sample
Java Generics (Notes)
2017 IDE for Java
[Java] Overview of Java
Java for statement
Kotlin functions and lambdas to send to Java developers
Specify Java / Kotlin compile-time options for Android apps
Summary of Java environment settings for myself [mac]
Initial settings for rewriting Java projects to Kotlin
Getting started with Kotlin to send to Java developers
Pre-introduction notes for JavaScript experienced learners of Java
A collection of simple questions for Java beginners
Introduction to kotlin for iOS developers ③-About gradle
Introduction to kotlin for iOS developers ①-Environment construction
Introduction to kotlin for iOS developers ②-Project creation
[Introduction to Java] Basics of java arithmetic (for beginners)
[Java] for statement, while statement
Expired collection of java
Predicted Features of Java
[Java] Significance of serialVersionUID
Get a list of MBean information for Java applications
Please note the division (division) of java kotlin Int and Int
[Java] Package for management
[For beginners] Quickly understand the basics of Java 8 Lambda
NIO.2 review of java
Review of java Shilber
[Java] for statement / extended for statement
Initialization of for Try to make Java problem TypeScript 5-4
Browse class objects in Kotlin (instead of Java class name.class)
java --Unification of comments
Frequently used Java generics
Countermeasures for Java OutOfMemoryError
[Java, Kotlin] Type Variance
History of Java annotation
NLP for Java (NLP4J) (2)
(Memo) Java for statement
NLP for Java (NLP4J) (1)
Introduction to Java for beginners Basic knowledge of Java language ①
List of frequently used Java instructions (for beginners and beginners)
NIO review of java
[Java] [Kotlin] Generically call valueOf and values of Enum
[Java10] Be careful of using var and generics together
[Java] Three features of Java
Links for each version (Japanese version) of Java SE API
[Null safety] Kotlin Java comparison memo Correct use of Null safety
How to execute WebCamCapture sample of NyARToolkit for Java
Summary of Java support 2018
Summary of file reading method for each Java file format