The two generic keywords out and in in Kotlin are the same as in Java? Extends and? Super is a one-to-one relationship

Declaring a list of a parent class and assigning a list object to a subclass is not allowed in Java (this is the same in Java and Kotlin)

package com.wuyue; import java.util.ArrayList; import java.util.List; Public class TestJavaG {public static void main(String[] args) {AClass AClass = new BClass(); List<AClass> list = new ArrayList<BClass>(); list <AClass> list = new ArrayList<BClass>(); AClass[] aArray = new BClass[3]; AClass[] aArray = new BClass[3]; Class BClass extends AClass {} class BClass extends AClass {}Copy the code


Of course, if you must, you can

// Subclass generic objects can be assigned to the parent class's generic type declaration List<? extends AClass> a_list = new ArrayList<BClass>(); // The following two statements will return an error when called, because we use? Extends removes this restriction but has the added effect that we can only use a_list and not modify it a_list.add(new AClass()); a_list.add(new BClass())Copy the code




A lot of people here don’t understand, what’s the use of this thing? It actually works. If you only want to use the value of a parameter in a function, and you don’t want to change it, then use this, okay? Extends greatly extends the scope of this function. Avoid a lot of trouble

package com.wuyue; import java.util.ArrayList; import java.util.List; Public class TestJavaG {// Not used? Extends wildcard so its argument must be static void printlnAll(List<AClass> aClassList) {for(AClass aClass : aClassList) { aClass.printlnInfo(); }} // use? Extends wildcard so its arguments can be static void printlnAll2 declared by any Aclsss subclass (List<? extends AClass> aClassList) {for(AClass aClass : aClassList) { aClass.printlnInfo(); } } public static void main(String[] args) { List<AClass> aList = new ArrayList<>(); List<BClass> bList = new ArrayList<>(); PrintlnAll (aList); PrintlnAll (bList); // This method will not compile the error because it is used in the method signature. Extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends wildcard extends printlnAll2(bList); } // class AClass {public voidprintlnInfo() {
        System.out.println("a class"); }} class BClass extends AClass {public voidprintlnInfo() {
        System.out.println("B class"); }}Copy the code



? Super and? Extends is just the opposite. Let’s look at a couple of examples

package com.wuyue; import java.util.ArrayList; import java.util.List; Public class TestJavaG {public static void main(String[] args) {BClass BClass = new AClass();  List<BClass> blist = new ArrayList<AClass>(); // Once we use? Super is a wildcard, so you don't get an error // It seems crazy, subclass declaration, superclass assignment, whatever? But it does work... List<? super BClass> blist2 = new ArrayList<AClass>(); } // class AClass {public voidprintlnInfo() {
        System.out.println("a class"); }} class BClass extends AClass {public voidprintlnInfo() {
        System.out.println("B class"); }}Copy the code



Now let’s look at what happens after it’s removed

package com.wuyue; import java.util.ArrayList; import java.util.List; public class TestJavaG { static void addOne(List<BClass> bClassList) { bClassList.add(new BClass()); } static void addOne2(List<? super BClass> bClassList) { bClassList.add(new BClass()); } public static void main(String[] args) { List<AClass> aClasses = new ArrayList<>(); AddOne (aClasses); AddOne2 (aClasses); } // class AClass {public voidprintlnInfo() {
        System.out.println("a class"); }} class BClass extends AClass {public voidprintlnInfo() {
        System.out.println("B class"); }}Copy the code

In Kotlin, out and in correspond to each other, right? Extends and? Super, I personally think Kotlin’s keywords are more concise than those in Java.

Out means? Extends means you can only read me, not write me. Because out means to export

In is the same thing as? Super means you can only write me, you can’t read me, because in means write inside

Package com.wuYUE // This avoids adding out and to every useinThis kind of keyword. // This is one way kotlin is more convenient than Java: write out or is directly at type creation timein 
interface Producer<out T> {
    fun produce(): T
}

interface Consumer<in T> {
    fun consume(): T
}Copy the code

// In javaz, these two forms are equivalent to List<? > alist = new ArrayList<BClass>(); List<? extends Object> alist2 = new ArrayList<BClass>(); Var TV :List<*> var tv2:List<out Any>Copy the code

Finally, there is no way to make a type judgment when using generics in Java. For example, if T is a generic, you will definitely get an error:

objectA instanceof TCopy the code


But the inline function +reified keyword in Kotlin does something similar:

inline fun <reified T> printTypeMath(item: Any) {
    if (item is T) {
        println("match")}else {
        println("miss")}}Copy the code


Here may also have some people a little confused, Java generics in the end is used for what, why the need for this thing, type erasure and type safety is what, here a simple extension, appropriate understanding of some, help us in the future work with good generics

In short, Java generics are what the Java compiler helps implement. The resulting bytecode does not contain the whole generics thing. List<String> List<Integer> is always a List when you compile it.

Type erasure is the substitution of type parameters in code directly with concrete classes at compile time. That’s all.

The advantage is that many errors can be found at compile time, which is a great convenience.

Here’s an example:

public class JavaCode {
    public static Object setAndReturn(Object obj) {
        return obj;
    }

    public static void main(String[] args) {
        Integer i = (Integer) setAndReturn(new String("abc")); }}Copy the code

So it’s obviously going to crush at execution time, because a string can’t be turned into an integer



We believe that in the actual development, this kind of mistake is certainly not rare. But if you write with generics, you don’t get this error at all, because you get an error at compile time, compile an error.

public class JavaCode {
    public static <T> T setAndReturn(T t) {
        return t;
    }

    public static void main(String[] args) {
        Integer i = (Integer) setAndReturn(new String("abc")); }}Copy the code

In addition, generics can save us a lot of code (cast)! Only for lazy people. Look at the following code:

class Fruit{}
class Apple extends Fruit{}
class Banana extends Fruit{}
class Bucket{
    public Apple getApple() {
        return apple;
    }

    public void setApple(Apple apple) {
        this.apple = apple;
    }

    Apple apple;
}

Copy the code

We only defined two types of fruit, and then we defined a basket, but this basket only supports apples, what if we want the basket to support other types of fruit?

class Bucket{
    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    Object object;
}Copy the code


This may seem like a good idea at this point, but we’ll eventually have to add a cast to this Bucket

Bucket bucket=new Bucket();
bucket.setObject(new Apple());
Apple apple=(Apple)bucket.getObject();Copy the code

It’s cumbersome, and if you’re not careful, you’ll get a cast error. Using generics is much easier:

class Bucket<T> {
    public T getObject() {
        return t;
    }

    public void setObject(T t) {
        this.t = t;
    }

    T t;
}Copy the code


This will be more convenient to use.

Bucket<Apple> bucket = new Bucket();
bucket.setObject(new Apple());
Apple apple = bucket.getObject();Copy the code

The thing to notice here, though, is that generics are a little bit more convenient to write. But after the compiler’s generic erasure, the bytecode representation is essentially the same.

Whether you are Bucket<Apple> or Bucket<Banana> is equivalent to writing Bucket<Object> when compiled. There’s no difference

Reference data: www.bilibili.com/video/av663…

Kaixue. IO/kotlin – gene…

             zhuanlan.zhihu.com/p/26965437