• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Type-safe generic code doubt

 
Rahul Choudhary
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


On line 10 there is a type-safe set as a parameter for the method dostuff and it accepts non generic Set s1. How can it not flag an error for one of it's element being a string(s1.add("1"))? From what I understand, integer 0(s1.add(0)) is accepted since Integer IS-A Number but that's not the case for String so how come no error ? Sorry if it's a silly doubt.
 
ayush raj
Ranch Hand
Posts: 60
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Rahul Choudhary : In main method , the set doesn't have any generic code , so whatever you add gets added (with warning that its not a type a safe operation, Remember compiler warnings are not the same as compiler error) without any error . However , when you are passing it to the method , you are specifying that the set now will contain only numbers in it . It does not check for the existing contents , but rather gets alert to whatever is added in future . Hence , if you now try to add a string in the set , you would surely be prompted with an error !!
 
Rahul Choudhary
Greenhorn
Posts: 22
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks @ayush raj, very well explained
 
Rahul Choudhary
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
However I have a similar doubt.


The above program compiles and runs fine.
But the program below give compiler error for every add() statement. Why? Isn't <? extends Object> refer to anything and everything that can be added to it?

 
ayush raj
Ranch Hand
Posts: 60
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to be very clear with this . By saying <? extends Object> , we are saying "I can be assigned a collection that is a subtype of LinkedList and typed for <Object>" and its like we swear that we wont be adding anything to the collection . <? extends> doesn't allow you to add either in the same method or in the different method . In the first case , its self explanatory that LinkedList<Object> will accept any of its sub-types also as Integer is-a Object , String is-a Object .... and so on . However , in the second case , even if you really want that the " LinkedList<? extends Object> l " should contain all that you have added , you need to change your code as the following :



Check it and tell me if its clear or not . And nothing to thank me .. thanks to Kathy Sierra and Bert Bates for the magnificent book provided by them
 
Dan Drillich
Ranch Hand
Posts: 1183
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good Day,

The beloved book of Kathy Sierra and Bert Bates speaks about this issue in page #602 under the title - "Mixing Generic and Non-generic Collections". It says -


Remember, the older legacy code was allowed to put anything at all (except primitives) into a collection. And in order to support legacy code, Java 5 and Java 6 allows for newer type safe code to make use of older code (the last thing Sun wanted to do was ask several million Java developers to modify all their exiting code).

However, just because the Java 5 compiler allows this code to compile doesn't mean it has to be HAPPY about it. In fact the complier will warn you that you're taking a big, big risk....


In our case, s1 obviously represents the legacy code.

Regards,
Dan
 
Himai Minh
Ranch Hand
Posts: 1316
6
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Rahul Choudhary buddy,
In the code you give, the compiler does not know what the linked list l will hold even though it is assigned to new LinkedList<Object>(). That is why adding any type of object to this linked list will not compile.
For instance, LinkedList<? extends Object> l can be assigned to new LinkedList<String>() or new LinkedList<Integer>() or new LinkedList<Double>() and etc... The compiler prevents you from adding a wrong type.



Look at this example:
 
Rahul Choudhary
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi ayush, dan and himai. From what all I have read in the posts from you guys is that if extends wild card is used it does not let you add anything. Not just <? extends Object> but something like <? extends Animal>. Also I have checked out other wild cards in K&B text.

  • <?>
  • <? extends XYZ>
  • <? super XYZ>
  • <Object>



  • Case1: <? extends XYZ> doesn't add anything from within method!


    Case 2: <?> doesn't add anything from within method!




    So can I safely understand it to be a rule that <? extends XYZ> and <?> as a method parameter won't allow anything to be added from within that method ass illustrated above?

    However, for <? super XYX> and <Object> it's even more peculiar.

    Case 3: <? super XYZ>


    it adds Dog object but not Animal object. It should right? In the program Dog extends Animal! A partial result.
    And if <? super Animal> is used, it adds both from within the method without any error! It shouldn't add Dog if <? super Animal> used right since Dog is subclass! What's the pattern or rule that I can understand here?

    Case 4: <Object>



    For the above program two things are happening. If I insert a type during instantiation (Dog or Animal) it gives compiler error saying "Object cannot be applied to Animal or Dog" and points to met(l1).
    But if I remove the type during instantiation, all works fine!

    Why this confusing thing is happening! I read up K&B but didn't find any such detailed explanation or if there I couldn't pinpoint Could I get help on each case please? Thanks again guys.
     
    Rahul Choudhary
    Greenhorn
    Posts: 22
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If explanation is given for such concept in K&B please could you provide me with page number.
     
    Himai Minh
    Ranch Hand
    Posts: 1316
    6
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Rahul buddy,


    This is a similar compiler design issue. The compiler won't let you add an animal to l2. It won't let you add an object to it neither. Why ? What if the animal is a Cat ? What if the object is a String/Double/Integer...?
    List<? super Dog> l2 tells the compiler that l2 can hold a list of Dogs. Or, it can hold a list of Animals or Objects. The followings are valid assignment:


    But you cannot add animal to l3 because l3 holds objects that is Dog or super type of Dog, which is animal and object.
    Assume you have a Cat class extending Animal.

    Adding a cat that is not in this hierachy Dog->Animal->Object won't make sense.
    For this reason, the compiler prevents you from adding any object type that is not a Dog.

    To add a Dog is fine because Dog is an Animal and is an Object.
    So,

     
    ayush raj
    Ranch Hand
    Posts: 60
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Rahul Choudhary wrote:If explanation is given for such concept in K&B please could you provide me with page number.


    Its given in page 618 describing briefly with what operation can be performed on which of the generics code and what cannot be performed . Read it thoroughly . That would make sense .

     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic