What's the purpose behind wildcards and how are they different from generics?

后端 未结 4 570
误落风尘
误落风尘 2020-12-01 06:40

I\'d never heard about wildcars until a few days ago and after reading my teacher\'s Java book, I\'m still not sure about what\'s it for and why would I need to use it.

相关标签:
4条回答
  • 2020-12-01 07:06

    You can store Dogs and Cats in a List<Animal>. That is not where wildcards are needed.

    Let's say you have a method that takes a list of animals:

    void foo(List<Animal> animals) {
        ...
    }
    

    Now you can't pass the method a List of Dogs -- it only takes an argument of type List<Animal>. You need a wildcard to make the method accept all kinds of Lists of Animals: List<Animal>, List<Dog>, List<Cat>, ...

    void foo(List<? extends Animal> animals) {
        ...
    }
    

    See

    http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html

    0 讨论(0)
  • 2020-12-01 07:10

    The wildcards do not make a lot of sense when you declare local variables, however they are really important when you declare a parameter for a method.

    Imagine you have a method:

    int countLegs ( List< ? extends Animal > animals )
    {
       int retVal = 0;
       for ( Animal cur : animals )
       {
          retVal += cur.countLegs( );
       }
    
       return retVal;
    }
    

    With this signature you can do this:

    List<Dog> dogs = ...;
    countLegs( dogs );
    
    List<Cat> cats = ...;
    countLegs( cats );
    
    List<Animal> zoo = ...;
    countLegs( zoo );
    

    If, however, you declare countLegs like this:

    int countLegs ( List< Animal > animals )
    

    Then in the previous example only countLegs( zoo ) would have compiled, because only that call has a correct type.

    0 讨论(0)
  • 2020-12-01 07:11

    Java generics are invariant.

    Suppose we have B extends A:

    • B is a subtype of A
    • an instanceof B is also an instanceof A

    Since Java arrays are covariant:

    • B[] is a subtype of A[]
    • an instanceof B[] is also an instanceof A[]

    However, Java generics are invariant:

    • List<B> is NOT a subtype of List<A>
    • a instanceof List<B> is NOT an instanceof List<A>.

    Wildcards are used to make it more flexible while preserving type safety.

    • a List<B> is a List<? extends A>

    References

    • Java Tutorials/Generics
      • Subtyping
      • More fun with wildcards

    Related questions

    • Any simple way to explain why I cannot do List<Animal> animals = new ArrayList<Dog>()?
    • java generics (not) covariance
    • What is the difference between <E extends Number> and <Number>?
    0 讨论(0)
  • 2020-12-01 07:17

    The difference between your 2 examples is simply that the first one is a list of generic/general animals - you can therefore add any type of animal to it, and any instance of a subclass of type Animal. (e.g. It can contain some dogs, some cats, some porcupines...) Whereas the second - List <? extends Animal> - will be a list of one specific subtype of class animal. It can be any one you choose (this is set each time at runtime), but only one. It will either be a list of dogs, or a list of cats, or a list of turtles... etc.

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