Home  >  Article  >  Java  >  Covariance, contravariance, extends and super selection methods of Java generics

Covariance, contravariance, extends and super selection methods of Java generics

PHPz
PHPzforward
2023-05-26 13:46:121291browse

To understand covariance and contravariance, we must first introduce:

According to the Liskov substitution principle, if C is a subclass of P, then P can replace C, that is P p = new C();
C inherits from P, denoted as C ebaed04dd9ce36c373c520f482f43ea6 and Listc0f559cc8d56b43654fcbe4aa9df7b4a There is no inheritance relationship

What is covariance

If F is covariant, when When C e08aff215a21644717230af7fb89ebc5 can be regarded as the parent class of ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a

? extend Number Can be seen as a type range, representing a certain subclass of Number

Arrays are covariant by default

Number[] numbers = new Integer[3];

What is contravariance

If F is contravariant. When C a15cf850c4664803f7aae846fd756a77= F(P)

Java provides a super to convert the invariant into a covariant Change, for example:

List<? super Number> list = new ArrayList<Object>(1);  //corrent

At this time, Listda50108ad159903fabe211f1543600e8 can be regarded as the parent class of ArrayLista87fdacec66f0909fc0757c19f2d2b1d

extends and super

First, let’s look at the implementation of Collection.add:

public interface List<E> extends Collection<E> { boolean add(E e); }

Will the following code report an error? ? extends Number does not match the Integer type

List<? extends Number> list = new ArrayList<Integer>(); // correct
list.add(Integer.valueOf(1));  //error

First of all, when the add method is called, the generic E automatically becomes a2b037db85f4e1df0e812b9647ac55a8

The second line reports an error, which means ? extends Number is not the parent class of Integer. Here we need to distinguish Lista2b037db85f4e1df0e812b9647ac55a8 is the parent class of ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a.

? extends Number can be regarded as a certain type in a type range, representing a certain subclass of Number, but it is not clear which subclass it is. It may be Float or Short. , or it may be a subclass of Integer (Integer is modified by final and cannot have subclasses. This is just a hypothetical situation). It only determines its upper bound as Number and does not determine the lower bound (there may be ? extends Number< Integer), therefore ? extends Number is not the parent class of Integer

change the above code A slight modification will make it correct:

List<? super Number> list = new ArrayList<Object>(); // correct
list.add(Integer.valueOf(1));  //correct

First of all, because of the inversion, Listda50108ad159903fabe211f1543600e8 is the parent class of ArrayLista87fdacec66f0909fc0757c19f2d2b1d. One line is correct.

The second line: ? super Number is the parent class of Integer, the reason is: ? super Number represents a certain parent class of Number , it may be Serializable or it may be Object But no matter which one it is, the parent class of Number must be the parent class of Integer, so the second line is also correct

Use extends Or is it super?

The copy method of java.util.Collections (JDK1.7) gives us the answer:

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    int srcSize = src.size();
    if (srcSize > dest.size())
        throw new IndexOutOfBoundsException("Source does not fit in dest");

    if (srcSize < COPY_THRESHOLD ||
        (src instanceof RandomAccess && dest instanceof RandomAccess)) {
        for (int i=0; i<srcSize; i++)
            dest.set(i, src.get(i));
    } else {
        ListIterator<? super T> di=dest.listIterator();
        ListIterator<? extends T> si=src.listIterator();
        for (int i=0; i<srcSize; i++) {
            di.next();
            di.set(si.next());
        }
    }
}
  • To convert from generics When a class gets data, use extends;

  • When you want to write data to a generic class, use super;

  • You need to both fetch and write , no wildcards are needed (that is, neither extends nor super are used)

private static <E> E getFirst(List<? extends E> list){
    return list.get(0);
}

private static <E> void setFirst(List<? super E> list, E firstElement){
    list.add(firstElement);
}

public static void main(String[] args) {
    List<Integer> list = new ArrayList<Integer>();
    setFirst(list, 1);
    Number number = getFirst(list);
}

The above is the detailed content of Covariance, contravariance, extends and super selection methods of Java generics. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete