aspose file tools*
The moose likes Beginning Java and the fly likes super generic and for loop Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "super generic and for loop" Watch "super generic and for loop" New topic
Author

super generic and for loop

Graeme Byers
Ranch Hand

Joined: Apr 16, 2004
Posts: 127
Hi, Reference S&B page 594.
I want to pass a List containg Dogs and (subclass) Terriers to a method.
But , whatever <type> I code at (1) <Animal> or <Dog> I get "incompatible type" at (2). I think this is a for-loop rather than a generics problem.
Thank you.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19672
    
  18

Your method accepts a list of Dog or any superclass - and that includes Object! If that is the case, how can your Objects make a sound?

You most likely want to change the list to List<? extends Animal> - a list of Animal or any subclass. Of course you need an Animal in the loop, not a Dog.

The general contract with wildcards is:
  • ? super X - you can pass X or any subclass, but not a superclass. For example, List<? super Dog> allows you to add Dog and Terrier objects but not Animal or Object objects - because the actual type could be Dog.
  • ? extends X - you can retrieve X or any superclass, but not a subclass (without casting). For example, from a List<? extends Animal> you can retrieve Animal and Object (through widening) objects, but not Dog or Terrier objects - because the actual type could be Cat which also extends Animal.


  • SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
    How To Ask Questions How To Answer Questions
    Graeme Byers
    Ranch Hand

    Joined: Apr 16, 2004
    Posts: 127
    Thank you for your reply. Perhaps I did not explain correctly.
    S&B page 594 has code (below)which looks (at first glance) as if addAnimal() (because it takes a List as an argument) adds all the elements in the List. Of course it only adds one extra Dog to the list.

    What types must I code in the for-loop to add() all its elements ?
    Graeme Byers
    Ranch Hand

    Joined: Apr 16, 2004
    Posts: 127
    Oops ! typo, read
    for (Dog d : animalListParm) { animalListParm.add(d) ; } // GB code (3)
    Mark Vedder
    Ranch Hand

    Joined: Dec 17, 2003
    Posts: 624

    Originally posted by Graeme Byers:
    Oops ! typo, read
    for (Dog d : animalListParm) { animalListParm.add(d) ; } // GB code (3)


    You can fix the typo in your actual post. Click the edit icon at the top of the post to do such. This will make it easier for people to help you.
    Rob Spoor
    Sheriff

    Joined: Oct 27, 2005
    Posts: 19672
        
      18

    Originally posted by Graeme Byers:
    What types must I code in the for-loop to add() all its elements ?

    Since the type is ? super Dog, that leaves three possible types:
    - Dog
    - Animal
    - Object

    Since you can't know which one it is, the widest one is the only one available when iterating: Object.

    Now of course, you can't add Object to your list - what if the actual type is Animal or Dog?

    Again the rules, but a bit more expanded:
  • ? super X:[LIST]
  • Add: X or a subclass / implementation. Basically anything that IS-A X
  • Iterate: only Object
  • ? extends X:
  • Add: nothing. You don't know the actual type, so you don't know what to add.
  • Iterate: X (or any superclass through widening)
  • X:
  • Add: X or a subclass / implementation. Basically anything that IS-A X
  • Iterate: X (or any superclass through widening)
  • [/LIST]

    Since you need to both add and iterate, you must limit your type to an exact class - no super or extends.


    As a side note, that code will most likely throw a ConcurrentModificationException. You are in fact modifying the list while iterating; that's not allowed. Imagine what would happen: you keep adding and adding and adding and adding, since every element that you encounter you add - and again, and again and again.
    Mark Vedder
    Ranch Hand

    Joined: Dec 17, 2003
    Posts: 624

    I'll just add this to Rob's fine answer:

    I am not sure if your goal was to add all of a list to another list, or if it was to better understand generic wildcards. (I suspect it is the latter, in which case Rob's answer should do the job.) If it is the former, you can use the addAll(Collection) method from the Collection interface to do such. For example:




    As an additional note on the ConcurrentModificationException... the ideal way to resolve that would be to use the addAll method I show above. An alternative would be to use a conventional for loop, being sure to get teh collection's size before starting to iterate over it:

     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
     
    subject: super generic and for loop