Java Generics (Wildcards)

后端 未结 6 1484
轻奢々
轻奢々 2020-11-22 10:17

I have a couple of questions about generic wildcards in Java:

  1. What is the difference between List and List

相关标签:
6条回答
  • 2020-11-22 10:57

    If you have a class hierarchy A, B is a subclass of A, and C and D both are subclass of B like below

    class A {}
    class B extends A {}
    class C extends B {}
    class D extends B {}
    

    Then

    List<? extends A> la;
    la = new ArrayList<B>();
    la = new ArrayList<C>();
    la = new ArrayList<D>();
    
    List<? super B> lb;
    lb = new ArrayList<A>(); //fine
    lb = new ArrayList<C>(); //will not compile
    
    public void someMethod(List<? extends B> lb) {
        B b = lb.get(0); // is fine
        lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
    }
    
    public void otherMethod(List<? super B> lb) {
        B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
        lb.add(new B()); // is fine, as we know that it will be a super type of A 
    }
    

    A bounded wildcard is like ? extends B where B is some type. That is, the type is unknown but a "bound" can be placed on it. In this case, it is bounded by some class, which is a subclass of B.

    0 讨论(0)
  • 2020-11-22 11:00

    There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

    Collection<? extends MyObject> 
    

    means that it can accept all object who have IS- A relationship with MyObject (i.e. any object which is a type of myObject or we can say any object of any subclass of MyObject) or a object of MyObject class.

    For example:

    class MyObject {}
    
    class YourObject extends MyObject{}
    
    class OurObject extends MyObject{}
    

    Then,

    Collection<? extends MyObject> myObject; 
    

    will accept only MyObject or children of MyObject(i.e. any object of type OurObject or YourObject or MyObject, but not any object of superclass of MyObject).

    0 讨论(0)
  • 2020-11-22 11:01

    In general,

    If a structure contains elements with a type of the form ? extends E, we can get elements out of the structure, but we cannot put elements into the structure

    List<Integer> ints = new ArrayList<Integer>();
    ints.add(1);
    ints.add(2);
    List<? extends Number> nums = ints;
    nums.add(3.14); // compile-time error
    assert ints.toString().equals("[1, 2, 3.14]"); 
    

    To put elements into the structure we need another kind of wildcard called Wildcards with super,

     List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
        List<Integer> ints = Arrays.asList(5, 6);
        Collections.copy(objs, ints);
        assert objs.toString().equals("[5, 6, four]");
    
        public static <T> void copy(List<? super T> dst, List<? extends T> src) {
              for (int i = 0; i < src.size(); i++) {
                    dst.set(i, src.get(i));
             }
        }
    
    0 讨论(0)
  • 2020-11-22 11:04

    Josh Bloch also has a good explanation of when to use super and extends in this google io video talk where he mentions the Producer extends Consumer super mnemonic.

    From the presentation slides:

    Suppose you want to add bulk methods to Stack<E>

    void pushAll(Collection<? extends E> src);

    – src is an E producer

    void popAll(Collection<? super E> dst);

    – dst is an E consumer

    0 讨论(0)
  • 2020-11-22 11:14

    In your first question, <? extends T> and <? super T> are examples of bounded wildcards. An unbounded wildcard looks like <?>, and basically means <? extends Object>. It loosely means the generic can be any type. A bounded wildcard (<? extends T> or <? super T>) places a restriction on the type by saying that it either has to extend a specific type (<? extends T> is known as an upper bound), or has to be an ancestor of a specific type (<? super T> is known as a lower bound).

    The Java Tutorials have some pretty good explanations of generics in the articles Wildcards and More Fun with Wildcards.

    0 讨论(0)
  • 2020-11-22 11:16

    Generic wildcards are created to make methods that operate on Collection more reusable.

    For example, if a method has a parameter List<A>, we can only give List<A> to this method. It is a waste for this method's funtion under some circumstances:

    1. If this method only reads objects from List<A>, then we should be allowed to give List<A-sub> to this method. (Because A-sub IS a A)
    2. If this method only inserts objects to List<A>, then we should be allowed to give List<A-super> to this method. (Because A IS a A-super)
    0 讨论(0)
提交回复
热议问题