[Java, Kotlin] Type Variance

invariant

// Java
interface Collection<E> ... {
    void addAll(Collection<E> items);
}

void copyAll(Collection<Object> to, Collection<String> from) {
    to.addAll(from); // !!! Would not compile with the naive declaration of addAll
}

Collection<String> is not a subtype of Collection<Object>

covariant

Java: Use-site variance; Kotlin: Type projections

// Java
interface Collection<E> ... {
    void addAll(Collection<? extends E> items);
}

void copyAll(Collection<Object> to, Collection<String> from) {
    to.addAll(from); // OK!
}

assign an instance of Collection<String> to Collection<? extends Object> read E from Producer Collection<? extends E> items

// Kotlin
class Array<T>(val size: Int) {
    fun get(index: Int): T { /* ... */ }
    fun set(index: Int, value: T) { /* ... */ }
}

fun copy(from: Array<out Any>, to: Array<Any>) {
    assert(from.size == to.size)
    for (i in from.indices)
        to[i] = from[i]
}

val ints: Array<Int> = arrayOf(1, 2, 3)
val any = Array<Any>(3) { "" } 
copy(ints, any)

assign an instance of Array<Int> to Array<out Any> from: Array<out Any> only with get function

Declaration-site variance

// Kotlin
abstract class Source<out T> {
    abstract fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // This is OK, since T is an out-parameter
    // ...
}

assign an instance of Source<String> to Source<Any> objects: Source<Any> Producer out Any

contravariant

Java: Use-site variance; Kotlin: Type projections

// Java
List<Animal> animals = new ArrayList<>();
List<? super Cat> cats = animals;
cats.add(new Cat());

assign an instance of List<Animal> to List<? super Cat> write Cat to Consumer List<? super Cat> cats

// Kotlin
class Array<T>(val size: Int) {
    fun get(index: Int): T { /* ... */ }
    fun set(index: Int, value: T) { /* ... */ }
}

fun fill(dest: Array<in String>, value: String) {
    // ...
}

assign an instance of Array<CharSequence> or Array<Any> to Array<in String> dest: Array<in String> only with set function

Declaration-site variance

// Kotlin
abstract class Comparable<in T> {
    abstract fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number
    // Thus, we can assign x to a variable of type Comparable<Double>
    val y: Comparable<Double> = x // OK!
}

assign an instance of Comparable<Number> to Comparable<Double> y: Comparable<Double> Consumer in Double

Declaration-site to Use-site variance

interface Comparator<in T> {
    int compare(T o1, T o2);
}

interface Foo {
    Comparator<Integer> getComparator();
}

in T -> contravariant upper Comparator<Integer> -> lower Comparator<? super Integer>

interface Comparator<T> {
    int compare(T o1, T o2);
}

interface Foo {
    Comparator<? super Integer> getComparator();
}

Use-site to Declaration-site variance

interface Baz<T, U> {
    Supplier<? extends U> baz(Consumer<? super T> consumer);
}

lower Consumer<? super T> -> upper Consumer<T> covariant -> out T

upper Supplier<? extends U> -> lower Supplier<U> contravariant -> in U

interface Baz<out T, in U> {
    Supplier<U> baz(Consumer<T> consumer);
}

Array Java covariant

Apple[] apples = new Apple[10];
Fruit[] fruits = apples;
fruits[0] = new Orange(); // throws an exception at runtime (ArrayStoreException or ArrayTypeMismatchException, respectively)
Apple apple = apples[0];

Kotlin invariant ensures compile time safety and prevents runtime errors

ref.

Recommended Posts

[Java, Kotlin] Type Variance
Java type conversion
[JAVA] Stream type
[Java] Enumeration type
Java Optional type
Java double type
[Java] Data type ①-Basic type
Java class type field
Type determination in Java
Java study # 1 (typical type)
[Java] About enum type
[Java] Date type conversion
[Java] List type / Array type conversion
Java learning memo (data type)
Try functional type in Java! ①
[Java] Precautions for type conversion
[Java] Type conversion speed comparison
[Java] Get KClass in Java [Kotlin]
Java study # 7 (branch syntax type)
Java Primer Series (Type Conversion)
Differences between "beginner" Java and Kotlin
Kotlin Class to send to Java developers
[Java] Data type / matrix product (AOJ ⑧ Matrix product)
java (use class type for field)
Java
Generics of Kotlin for Java developers
Java
[Java] Correct comparison of String type
[Java & Kotlin] Create multiple selectable RecyclerView
[Android] Convert Android Java code to Kotlin
How to use Java enum type
[Java] Express Enum type without using Enum (enumeration) type
[Java Siler] About type inference by var
[Java] Implicit type cast (AOJ10-sum of numbers)
Kotlin Class part.2 to send to Java developers
Relationship between kotlin and java access modifiers
Java date data type conversion (Date, Calendar, String)
Regarding String type equivalence comparison in Java
[Easy-to-understand explanation! ] Reference type type conversion in Java
Use PostgreSQL data type (jsonb) from Java
About Spring Dependency Injection using Java, Kotlin
Find out how Java protects type integrity
[Java ~ Variable definition, type conversion ~] Study memo
Convert all Android apps (Java) to Kotlin
[Personal memo] Java data type is annoying
[Java] Data type / string class cheat sheet
Java study # 3 (type conversion and instruction execution)
Notes on operators using Java ~ String type ~
[Java] Introducing the Generics Boundary Wildcard Type
[For beginners] Difference between Java and Kotlin
[Java] Convert Object type null to String type
A Java engineer compared Swift, Kotlin, and Java.
Kotlin scope functions to send to Java developers
Directory change monitoring method memo (Java, Kotlin)
[Basic knowledge of Java] About type conversion
[Kotlin] Delete files with duplicate contents [Java]
Interoperability tips with Kotlin for Java developers
[Java] Comparison of String type character strings
Java Summary of frequently searched type conversions
What Java programmers find useful in Kotlin
Introduction to kotlin for iOS developers ④-Type