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

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

PHPz
Release: 2023-05-26 13:46:12
forward
1365 people have browsed it

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 < P

What is invariant

If F is invariant , when C

Except for example, Integer is a subclass of Number, according to the Liskov substitution principle

Number number = new Integer(1);  //correct
Copy after login

But if you write like this, an error will be reported

List<Number> list = new ArrayList<Integer>(1);  //error
Copy after login

Although Number and Integer have an inheritance relationship: Integer < Number, in Java, generics are unchanged by default, so they can also be regarded as List<Number> and List<Integer> There is no inheritance relationship

What is covariance

If F is covariant, when When C <= P, then F(C) <= F(P)

Java provides an extends to convert invariance into covariance, for example:

List<? extends Number> list = new ArrayList<Integer>(1);  //corrent
Copy after login

At this time, List<? extends Number> can be regarded as the parent class of ArrayList<Integer>

? 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];
Copy after login

What is contravariance

If F is contravariant. When C <= P, then F(C) >= 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
Copy after login

At this time, List<? super Number> can be regarded as the parent class of ArrayList<Object>

extends and super

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

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

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
Copy after login

First of all, when the add method is called, the generic E automatically becomes <? extends Number>

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

? 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
Copy after login

First of all, because of the inversion, List<? super Number> is the parent class of ArrayList<Object>. 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());
        }
    }
}
Copy after login
  • 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);
}
Copy after login

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!

Related labels:
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Issues
Install JAVA
From 1970-01-01 08:00:00
0
0
0
Unable to install java
From 1970-01-01 08:00:00
0
0
0
Can java be used as the backend of the web?
From 1970-01-01 08:00:00
0
0
0
Is this in Java language?
From 1970-01-01 08:00:00
0
0
0
Help: JAVA encrypted data PHP decryption
From 1970-01-01 08:00:00
0
0
0
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template