• Post Reply Bookmark Topic Watch Topic
  • New Topic

Generics question  RSS feed

 
Adam Chalkley
Ranch Hand
Posts: 257
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks Campbell that makes sense

just a quick follow up sorry for asking so many questions



why does the following code work? I thought <? super Player> meant any object that is a super class of Player,but FootballPlayer is a sub class of player,that confuses me
 
Henry Wong
author
Sheriff
Posts: 23188
124
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Adam Chalkley wrote:
if you just get a compilation error when you try to add something?


Congrats. You have moved from not understanding generic wildcards, to understanding generic wildcards along with severe limitations...   ... of course, now the next step is, can you work with those limitations? Or do you discard wildcards as you now seem to conclude that it is useless?

Here is an example...

Let's say you need to write a way to tag animals. Basically, put a tracker on animals, and then be able to report where they are, etc.  This code, of course, doesn't need to add() any animals, or even care what kind of animals it is. It just needs to, given a list of animals, tag it... like so...



The problem with this code is ... it doesn't work with List<Tiger>, List<Lion>, and List<Bear>, oh my.

To make it work, you have a few options. You can *not* use generics; use casting with a List with no generics (since that works in compatibility mode). This is bad!!

You can write overloaded methods, one that takes a List<Tiger>, one that takes a List<Lion>, one that takes a List<Bear>, which of course, not only doesn't work (due to generic type erasure), but even if it did, requires lots and lots of overloaded methods. This is worse.

Or you can use wildcards...



Henry
 
Stephan van Hulst
Saloon Keeper
Posts: 7376
130
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wildcards are very useful. They allow you to call methods on a wide variety of generic types. Yes, it's true that you can't call add() on a List<? extends Something>, but List has many other useful methods. What if we don't want to add anything to a list, but just want to get things out of it? Here's a silly example: Let's say we want to fill a FruitBowl:

If we go to the shop and buy a bag of oranges, it seems reasonable to fill the fruit bowl from the bag of oranges:

Assuming that Bag is a Collection (and thus an Iterable), the compiler will report an error because a Bag<Orange> can not be assigned to an Iterable<Fruit>. What a drag! The fillByTakingFrom() method doesn't care about the exact type of sourceOfFruits, as long as it can just get fruits out of it!

Similarly, if we have a List<Object>, it would be nice if we could use it to empty our fruit bowl into:

We fix it like this:

In general, when you have a variable of a generic type, it should be covariant (use the extends keyword) when you only need to call methods (e.g. sourceOfFruits.iterator()) that use the generic type argument (Fruit) only in the return type.

When you only needs to call methods (e.g. fruitContainer.addAll()) that use the generic type argument only in their method parameters, the variable should be contravariant (use the super keyword).

When you need to use the generic type argument in both method parameters and return types, the variable should be invariant (use neither extends nor super).

Finally, when you don't care about the generic type argument at all, you use an unbounded wildcard (e.g. List<?>). That case is fairly rare, but you can see examples in the equals() method of the Hierarchy and Team classes I wrote earlier.
 
Campbell Ritchie
Sheriff
Posts: 54495
150
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Adam Chalkley wrote:thanks Campbell . . .
That's a pleasure
I thought <? super Player> meant any object that is a super class of Player,but FootballPlayer is a sub class of player,that confuses me
  • 1: A FootballPlayer IS‑A Player.
  • 2: For the purposes of generics, remember that every type is a subtype of itself, and also a supertype of itself.
  •  
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks Stephan and Henry for the detailed posts means a lot I will study this now

    just a quick follow up to Campbell



    Player has a method called getName() how come I can't access getName()? it only gives me the options to use the methods toString,getClass etc

    please note Sim,Jim,and Tim are all instances from Player with Jim been a  BasketballPlayer and Tim being a FootballPlayer
     
    Henry Wong
    author
    Sheriff
    Posts: 23188
    124
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Adam Chalkley wrote:
    Player has a method called getName() how come I can't access getName()? it only gives me the options to use the methods toString,getClass etc

    please note Sim,Jim,and Tim are all instances from Player with Jim been a  BasketballPlayer and Tim being a FootballPlayer


    A List<? super Player> reference can point to a List<Object> instance. After all, Object is a super class of Player right?

    Based on the Wildcard, the compiler can't confirm that the element IS-A Player, hence, can't assume that the Player method exists.

    Henry
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    this may be the longest thread on coderanch(laughs) but it is a pretty long complex topic I guess,

    one thing I don't get and I've been reading countless of forums is when people say get out and put in I'll copy and paste someones explanation that I don't understand

    The distinction is important because extends tells you what you can get out of a class (you get at least this, perhaps a subclass). super tells you what you can put into the class (at most this, perhaps a superclass).


    I don't understand what he/she means by this ^^

    thanks
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    "Get out" means calling a method that has a generic return type. For instance, List.iterator() returns an Iterator<E>. You can use it to get elements out of the list.

    "Put in" means calling a method that has a generic method parameter. For instance, List.replaceAll(UnaryOperator<E> operator) accepts a UnaryOperator<E>. You can use it to put elements into the list.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Note that "put in" doesn't necessarily mean storing objects for later. Comparator.compare(T o1, T o2) has generic method parameters, so when you call it, you can say that you put objects into the comparator. It doesn't store those objects, it just uses them to perform its comparison operation. Indeed, because you only ever put generic arguments into Comparator and never get them out, you should always declare variables of Comparator as Comparator<? super Something>.
     
    Knute Snortum
    Sheriff
    Posts: 3715
    90
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Oracle has a good tutorial on Generics, Wildcards, and Sublist:

    https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

    Does that help any?
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks Stephan and Knute

    I read the oracle documentation it's not bad but doesn't give enough examples

    here is a good example I found on a forum I understand a parts of it but not it all I'll copy and paste it here in quotes.I will put a comment // with a number what I don't understand beside the bullet points and explain below



    extends

    The wildcard declaration of List<? extends Number> foo3 means that any of these are legal assignments:


    Reading - Given the above possible assignments, what type of object are you guarenteed to read from List foo3:
    You can read a Number because any of the lists that could be assigned to foo3 contain a  Number or a subclass of Number. // understood
    You can't read an Integer because foo3 could be pointing at a List<Double>. // understood
    You can't read a Double because foo3 could be pointing at a List<Integer>. // understood
    Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:
    You can't add an Integer because foo3 could be pointing at a List<Double>. // understood
    You can't add a Double because foo3 could be pointing at a List<Integer>. // understood
    You can't add a Number because foo3 could be pointing at a List<Integer>. // 1 don't understand
    You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of  T.

    super

    Now consider List <? super T>.

    The wildcard declaration of List<? super Integer> foo3 means that any of these are legal assignments:


    Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:
    You aren't guaranteed an Integer because foo3 could be pointing at a List<Number> or  List<Object>. // understood
    You aren't guaranteed an Number because foo3 could be pointing at a List<Object>. // understood
    The only guarantee is that you will get an instance of an Object or subclass of Object (but you don't know what subclass). // 2 don't really understand
    Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:
    You can add an Integer because an Integer is allowed in any of above lists. // 3 don't understand
    You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists. // 4 don't understand
    You can't add a Double because foo3 could be pointing at a ArrayList<Integer>. // understand
    You can't add a Number because foo3 could be pointing at a ArrayList<Integer>. // 5 don't understand
    You can't add a Object because foo3 could be pointing at a ArrayList<Integer>. 6 // don't understand
    PECS

    Remember PECS: "Producer Extends, Consumer Super".

    "Producer Extends" - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List<? extends Integer>. But you cannot add to this list.
    "Consumer Super" - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List<? super Integer>. But there are no guarantees what type of object you may read from this list.
    If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List<Integer>.
    Example

    Note this example from the Java Generics FAQ. Note how the source list src (the producing list) uses extends, and the destination list dest (the consuming list) uses super:

    public class Collections {
      public static <T> void copy(List<? super T> dest, List<? extends T> src) {
          for (int i = 0; i < src.size(); i++)
            dest.set(i, src.get(i));
      }
    }




    1)  why can't we add a number if Integer is a subclass of Number
    2)  don't really understand hard to explain
    3)  why are we allowed add an Integer what if the list<? super T> is pointing to List<Number> or List<Object>?
    4) same question as number three but also why are we even allowed a sub class when we stay super T meaning T or any super class of T how can we add sub classes when we didn't say extends
    5) why can't we add a number if Number is a super class of Integer

    6) why can't we add an object if Object is a super class of Integer also



    thanks
     
    Knute Snortum
    Sheriff
    Posts: 3715
    90
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator


    1)  why can't we add a number if Integer is a subclass of Number 

    Because Number is NOT an Integer, although Integer IS-A Number.

     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks Knute that makes sense,

    in regards to <? super T>

    and also in regards to the example above why is this valid

    "You can add an Integer because an Integer is allowed in any of above lists."

    thanks
     
    Knute Snortum
    Sheriff
    Posts: 3715
    90
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    In this case, foo3 can be instantiated as an Integer, a Number, or an Object.  And since nothing is a superclass of Object, that's the end.  So what class is guaranteed to be an Integer, Number, and Object?  Only an Integer.  The element in the list has to, in a sense, match all three of the classes because you don't know which of the three the List will be instantiated as.
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks for all the input guys starting to finally make sense now,

    but I do get an error when I try to run some code




    when I try to run

    [code]



    I get an out of bounds error but how is it possibly out of bounds from what I can see I am in the right range

    Exception in thread "main" java.lang.IndexOutOfBoundsException: Source does not fit in dest
    at java.util.Collections.copy(Unknown Source)
    at Main.main(Main.java:83)


     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    hi guys ignore the last post

    the error I was getting was with a different line of code



    If anyone wants to say why I got that error with the code above would greatly be appreciated
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Adam Chalkley wrote:1)  why can't we add a number if Integer is a subclass of Number

    Because not all numbers are integers. What if my Number variable holds a reference to a Double?

    2)  don't really understand hard to explain

    Object is simply the hard upper bound of all generic type parameters. That's because ALL objects derive from Object.

    3)  why are we allowed add an Integer what if the list<? super T> is pointing to List<Number> or List<Object>?

    So? You're allowed to add an Integer to a List<Object>. Integer is an Object after all.

    4) same question as number three but also why are we even allowed a sub class when we stay super T meaning T or any super class of T how can we add sub classes when we didn't say extends

    The super and extends keywords are used to determine the lower and upper bounds of the type parameter, not of the types of objects you can put in a collection. When you say List<? super Number> list, that means that list can hold a List<Number> or a List<Object>. But you can ALWAYS put an Integer into both of those two types of lists. You limit the generic type argument of the list you put in the variable, not the objects you put in the list.

    5) why can't we add a number if Number is a super class of Integer

    Because the Number could actually be a Double.

    6) why can't we add an object if Object is a super class of Integer also

    Because the Object could actually be a String.
     
    Henry Wong
    author
    Sheriff
    Posts: 23188
    124
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Adam Chalkley wrote:
    If anyone wants to say why I got that error with the code above would greatly be appreciated


    Here is the JavaDoc for the copy() method...

    https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#copy-java.util.List-java.util.List-

    Specifically... this line ... "The destination list must be at least as long as the source list."

    Henry

     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks Henry
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks Stephan much appreciated that makes sense
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    so this is common practice when written a method that reads from a list and a method that writes to a list so the question is why do we have to even use the wildcard in this example




    if we remove the wildcard and just put T it woks just the same as it would with the ?,so the question is whats the point of the ? in this situation



    both work just fine and do the same thing?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    No. If T == Integer, you can not use the second version to add a an Integer to a List<Number>, because the method expects a List<Integer>.
     
    Jesse Matty
    Ranch Hand
    Posts: 55
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:General rough rule of thumb, which I am sure Henry has already told you.
    If you have List<? extends Foo> you can get things out of it and be confident you can use them as a Foo. That means, “Whatever is in this List will be a Foo. It might be a subtype of Foo, but I don't know that. It won't matter, anyway.”
    If you have a List<? super Foo> you can take things which you are confident are a supertype of Foo and put them in it. That means, “If you add a Foo to this List, I can be sure it will fit in. You can also insert a supertype of Foo, but I don't know which type. It won't matter, anyway.”

    ? extends→remove. Don't add
    ? super→insert. Don't remove.

    I don't think your example with T extends E will compile. I agree: there probably is no point in trying to turn a List<Foo> into a List<? extends Foo>. Whoever told you about boxes for puppies (maybe Stephan?) showed you why you can't add anything to the List<? extends T>.



    What is the point of  writing List<? extends Foo> I have always written List<Foo> and been able to add anything  that extends foo to it.Now my foo class has always been abstract though
     
    Campbell Ritchie
    Sheriff
    Posts: 54495
    150
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Please review Henry's post where he explains how you can get Animals out of a List<Lion> or List<Tiger> only if you declare its type as List<? extends Animal>
    Remember:
    ? extends Foo ⇒ take things out.
    ? super Foo    ⇒ put things in.
     
    Jesse Matty
    Ranch Hand
    Posts: 55
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Please review Henry's post where he explains how you can get Animals out of a List<Lion> or List<Tiger> only if you declare its type as List<? extends Animal>
    Remember:
    ? extends Foo ⇒ take things out.
    ? super Foo    ⇒ put things in.



    sorry it was late last night I meant to write  what is the point of declaring a List as <? super Foo>

     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jesse Matty wrote:What is the point of  writing List<? extends Foo> I have always written List<Foo> and been able to add anything  that extends foo to it.Now my foo class has always been abstract though

    Earlier in this thread I explained that the generic type bound doesn't affect what elements you can put in a collection. It affects what collections you can assign to a variable.

    If your method accepts a List<T>, and T is Number, you will only be able to pass in a List<Number>. If your method accepts a List<? extends T>, you are able to pass a List<Number>, List<Integer>, List<Double>, etc. etc. If all you do in your method is retrieve elements from the list, the declaration with wildcard is far superior because it gives the caller of your method much more freedom to pass the collection that it wants.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jesse Matty wrote:sorry it was late last night I meant to write  what is the point of declaring a List as <? super Foo>

    I explained that in my last response to Adam.
     
    Jesse Matty
    Ranch Hand
    Posts: 55
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Stephan van Hulst wrote:
    Jesse Matty wrote:sorry it was late last night I meant to write  what is the point of declaring a List as <? super Foo>

    I explained that in my last response to Adam.


    I think I understand now but what would be use of doing that? why have a list that can hold any kind objects that  a object extends? isn't it bad practice to declare a list that can hold  a type object?  Also wouldn't  you have to declare type on the right side of the assignment? what is benefit to writing List<? super Double> number = new ArrayList<Number>(); as opposed to writing List<Number> number =new ArrayList<Number>():
     
    Henry Wong
    author
    Sheriff
    Posts: 23188
    124
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jesse Matty wrote: what is benefit to writing List<? super Double> number = new ArrayList<Number>(); as opposed to writing List<Number> number =new ArrayList<Number>():

    Simply, in my humble opinion, that line serves zero purpose -- except for maybe as a teaching example.  There is really no purpose of making a wildcard the only reference to an instance. Wildcards are needed so that you can have code that can work with multiple generic types, and since it works with missing information, it is generally a good idea to have references (that are not wildcards) pointing at the instance. This is why wildcards make great method parameters.

    Henry
     
    Adam Chalkley
    Ranch Hand
    Posts: 257
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thanks guys for all the input much appreciated

    Stephan you mention that if you put <? extends T> instead of <T> now you can pass a list<Number> list<Integer> if you pass a list<Number> but the compiler only knows at run time what T is going to be?

    so for example if you pass list<Number> that will work also if you pass list<Integer> that should work also because it is happening at run time?

    also why can we not say <T extends T> ie T or a subclass of T

    or T<? extends T> obj ie an object of type T with any object T or that is a sublass of T?



    thanks
     
    Campbell Ritchie
    Sheriff
    Posts: 54495
    150
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Adam Chalkley wrote:. . . the compiler only knows at run time . . .
    The compiler does not run at runtime. It therefore doesn't know full stop.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jesse Matty wrote:why have a list that can hold any kind objects that  a object extends? isn't it bad practice to declare a list that can hold  a type object

    Your understanding of what a wildcard means is wrong. List<? extends Number> does NOT mean "a List that can hold any kind of Number". That's what List<Number> means, by virtue of polymorphism. List<? extends Number> means "any kind of List, as long as its generic type argument is a subtype of Number. You use wildcards to indicate that you don't really care about the exact type of the List, not the exact type of its elements.

    Using List<Number> says: "I need *exactly* a List<Number>, you're not allowed to give me a List<Integer> or a List<Object> or any other kind.

    Using List<? extends Number> says: "I need any kind of List, I don't care which one, as long as I can get Numbers out of it. It could be a List<Number>, a List<Integer> or a List<Double>, I don't give a damn.

    Using List<? super Number> says: "I need any kind of List, I don't care which one, as long as I can put Numbers into it. It could be a List<Number>, or a List<Object>, I don't give a damn.

    So once again, why does any of this matter? Take a look at Collection.addAll(). It accepts a Collection<? extends T>. That allows me to do the following:

    It's great that we can do that! Imagine if the designers had written addAll() to accept a Collection<T> instead. That sucks, because now I have to convert my Collection<Orange> to a Collection<Fruit> before I can add it to fruits!
     
    Jesse Matty
    Ranch Hand
    Posts: 55
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I know all what you said  but my question is  what exactly List <? super ObjectKind> useful for? I know what List<? extends  ObjectKind> is useful for and  I use it  to add ArrayLists to other ArrayLists  in conjunction with the addAll() method and to pass lists of of objects to methods that extend a base class, but <? super ObjectKind> I see no use for. Why would someone not care what kind of list they are putting objects into? wouldn't most programmers like to put objects into the correct list type so they can call the methods they need on them? If I have a  list of Soliders I can see adding lists of  knights swordsmen  or archers to it.  That makes sense. But to add knight to a list of living things  that may include plants bacteria or fungus makes no sense.  Then to add a knight to list of objects that include plants ,rocks, cars, numbers or words makes even less sense. I see no use practical use for <? super ObjectKind>.
     
    Daniel Cox
    Ranch Hand
    Posts: 167
    9
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jesse Matty wrote:...my question is  what exactly List <? super ObjectKind> useful for?

    Read Campbell's post
    Campbell Ritchie wrote:Remember:
    ? extends Foo ⇒ take things out.
    ? super Foo    ⇒ put things in.

    This can come in handy if you're writing code where you extract Animals from a list and add them to another list, for example:

    List<? super Animal> recipient
    Whatever list "recipient" refers to, you can always use the "recipient" reference to add Animals into the list but you cannot extract Animals.

    List<? extends Animal> donor
    Whatever list "donor" refers to, you can always use the "donor" reference to extract Animals from the list (if it is not empty) but you cannot add Animals.

    In both cases, you can use List<Animal>, but using a wildcard makes your code more flexible.

    Jesse Matty wrote:But to add knight to a list of living things  that may include plants bacteria or fungus makes no sense.

    With generics, it's okay to have a list of living things (List<LivingThing> list) composed of knights (humans), plants, bacteria, fungi etc, as long as you're okay with extracting each item in the list as a LivingThing (no need to cast) and then processing the items polymorphically.

     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7376
    130
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    There are more generic types than just List. What about Comparator or Consumer? Take a look at the Collection.forEach() method, or the List.sort() method.

    Should I really have to convert my Consumer<Object> to a Consumer<Banana> before I can print each banana?

    Should I really have to convert my Comparator<Fruit> to a Comparator<Banana> before I can sort a list of bananas?

    Thankfully, the forEach() and sort() method accept contravariant types: "I don't care what the exact type of the consumer or comparator that you're giving me is, as long as it swallows bananas".
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!