What is the difference between and ?

后端 未结 2 1480
独厮守ぢ
独厮守ぢ 2020-11-28 06:30

What is the difference between this method declaration:

public static  List process(List nums){

a

相关标签:
2条回答
  • 2020-11-28 07:17

    The first allows process of a List<Integer>, a List<Double>, etc. The second doesn't.

    Generics in Java are invariant. They're not covariant like arrays.

    That is, in Java, Double[] is a subtype of Number[], but a List<Double> is NOT a subtype of List<Number>. A List<Double>, however, is a List<? extends Number>.

    There are good reasons for generics being invariant, but that's also why the extends and super type are often necessary for subtyping flexibility.

    See also

    • Java Tutorials/Generics/Subtyping
      • Explains why generics invariance is a good thing
    • More fun with wildcards
      • Explains some uses of super and extends for bounded wildcards
    • Java Generics: What is PECS?
      • This discusses the "Producer extends Consumer super" principle
      • Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
    0 讨论(0)
  • 2020-11-28 07:22

    The latter method (the one without <E extends Number>) will only accept a parameter of exactly type List<Number> and will it always return a List<Number>. For example, it will not accept List<Integer>.

    The former method (the one with <E extends Number>) is a generic method, meaning it can accept different types of Lists and it will return the same type of List, as long as the Lists are lists of something that extends Number, e.g. List<Integer>.

    Example:

    import java.util.ArrayList;
    import java.util.List;
    
    public class ProcessGenerics {
    
        List<Number>  listNumber  = new ArrayList<Number>();
        List<Integer> listInteger = new ArrayList<Integer>();
        List<Double>  listDouble  = new ArrayList<Double>();
    
    
        public static
            List<Number> processWithoutExtends(List<Number> nums){ return nums; }
    
        List<Number>  resultN = processWithoutExtends(listNumber);  // OK
      //List<Integer> resultI = processWithoutExtends(listInteger); // compile-error - method not applicable
      //List<Double>  resultD = processWithoutExtends(listDouble);  // compile-error - method not applicable
    
    
        public static <E extends Number>
            List<E> processWithExtends(List<E> nums){ return nums; }
    
        List<Number>  resultN2 = processWithExtends(listNumber);  // OK
        List<Integer> resultI2 = processWithExtends(listInteger); // OK
        List<Double>  resultD2 = processWithExtends(listDouble);  // OK
    
    }
    

    See a similar explanation in the Wildcards chapter in the Generics Lesson in the Java Tutorials:
    http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html

    See also How to cast a list of inheriting objects to a collection of objects in Java? Both questions are really about generics and subtypes, e.g. whether List<Integer> is a subtype of List<Number> (it's not!!!).

    0 讨论(0)
提交回复
热议问题