Generics - super
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
But the compiler is OK with this:
Why does the compiler accept this notation? Could this List ever been anything other than type Horse? If the object type must be specified, surely the List type has to be the same?
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Originally posted by Paul Kemp:
....
But the compiler is OK with this:
Why does the compiler accept this notation? Could this List ever been anything other than type Horse? If the object type must be specified, surely the List type has to be the same?
Hi Paul,
The above code is saying that you can take any type which is Horse and any SUPERCLASS. So Horse, Animal and Object can be accepted.
If you had said something like:
Then this means any Horse or subclass of Horse is accepted.
If you do not use any wild card syntax then the type of object must match:
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
This is *not* allowed because an ArrayList<Horse> can't be treated as a List<Animal>... for example...
You can add a Dog, Cat, Chicken, etc., to a List<Animal>, as they are all animal types. However, you can't add any of those animal types to an ArrayList<Horse>.
Henry
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
The above code is saying that you can take any type which is Horse and any SUPERCLASS. So Horse, Animal and Object can be accepted.
How?
If I have defined new ArrayList<Horse>(); how can it take anything else?
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
List<? super Horse> myList = new ArrayList<Horse>();
The above code is saying that you can take any type which is Horse and any SUPERCLASS. So Horse, Animal and Object can be accepted.
No... This is *not* true. The code is saying that it is of an unknown type, that happens to be a horse type or a super of a horse type.
If you try to iterate through the list, the element type return is an Object type, as it doesn't know what type to return.
Furthermore, if you want to add items to the list, you must add horse types, or objects which are subclasses of horse types, as that is the only way to guarrantee the correct type, no matter what super type it is supposed to be.
Henry
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
no no it's not like that.
you cannot add new Animal().
The statement says you can assign list of any Horse Object or its super class object.
means
List<? super Horse> myList = new ArrayList<Horse>();
List<? super Horse> myList = new ArrayList<Animal>();
List<? super Horse> myList = new ArrayList<Object>();
and you cannot assign list of any horse subclass or any sibling class
List<? super Horse> myList = new ArrayList<WhiteHorse>();//wrong
List<? super Horse> myList = new ArrayList<Dog>();
this will guarantee that your list will contain only Horse object or its subclass objects, not any sibling class object.
[ December 09, 2008: Message edited by: Punit Singh ]
SCJP 6
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
If you had said something like:
List<? extends Horse> myList = new ArrayList<Horse>();
Then this means any Horse or subclass of Horse is accepted.
This also needs some clarification. In this case, the list is holding some unknown type, which happens to extend the horse type. If you iterate through the list, you will get a horse type, as all classes that extend a horse IS-A horse.
You can *not* add any items to this list. The reason is that you don't know what type it is, and unlike the previous post, there is no type that is all possible types that extend horse.
Henry
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Are these bits of code actually the same? They both allow polymorphism on subclasses of Horse...
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
and I am completely lost when it comes to Generics. I do not understand them at all when combined with polymorphism, collections, and wildcards all at once.
If anyone knows any guides that are VERY simple... like the "around the campfire" stories. A guide that tells a story in a way that makes since. Please post them here as this is a very important topic that I really want to fully grasp.
TY
SCJA
~Currently preparing for SCJP6
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
public void addAnimal(List<? super Dog> animals) {
animals.add(new Dog()); // adding is sometimes OK with super
}
public static void main(String[] args) {
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Dog());
animals.add(new Dog());
AnimalDoctorGeneric doc = new AnimalDoctorGeneric();
doc.addAnimal(animals); // passing an Animal List
}
Take this code. Here in addAnimal() method we are adding Dog objects.
but accepting any list that containg Dog or any superclass.
So if we call addAnimal(ArrayList<Animal>()), then we can add Dog object in this list as Dog extends Animal.
Now think another case: change the addAnimal() method
public void addAnimal(List<Animal> animals) {
animals.add(new Dog()); // adding is sometimes OK with super
}
and call it:
addAnimal(new ArrayList<Cat> ) ;
Suppose Java compiler had made List<Animal> to accept ArrayList<Cat> then what will happen?
animals.add(new Dog());
we will add Dog object in a Cat list. And generics is only compile time checking. After that for jvm it is like non-generics code.
JVM cannot catch that we are adding Dog object in Cat list.
for array
Animal[] catArr=new Cat[5];
catArr[0]=new Dog();
Array has both compile time checking and runtime checking, here compiler will allow this as catArr is Animal array.
But at runtime JVM will check that the actual array Object type is Cat and it will throw ArrayStoreException.
But for generics only compile time checking is performed, there is no runtime checking. So compiler will not allow any case that allow to add
List<Dog> to have Cat Object.
I think this will help you.
[ December 09, 2008: Message edited by: Punit Singh ]
SCJP 6
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Are these bits of code actually the same? They both allow polymorphism on subclasses of Horse...
List<Horse> myList = new ArrayList<Horse>();
myList.add(new ShireHorse());
List<? super Horse>myList2 = new ArrayList<Horse>();
myList2.add(new ShireHorse());
Functionally, both code snippets are effectively the same. However, there are differences. Try to iterate through each list. And try to use the lists themselves.
You can easily tell that they are not the same by assigning them to each other...
myList2 = myList; // Okay
myList = myList2; // Not Okay
Henry
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Fair Enough.
So the code
on the left hand side of the = is really saying, that myList2 could be of type Horse, Animal, Mammal, Object, the compiler doesn't know, so long as it is above Horse in the hierarchy we're ok, so to play safe we will return type Object here.
Meanwhile on the right hand side of the =, myList2 could contain type Horse, ShireHorse, MyLittlePony, etc, but nothing above Horse in the scheme of things.
So one final question on this if I may...
The code above works OK. In fact, I can replace new ArrayList<Animal>(); with new ArrayList<Object>; new ArrayList<Horse>; and they all compile, so what is the significance of my choice of object on the right-hand side of the equals...? Especially if List<? super ShireHorse>myList2 returns Objects anyway....
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
As an example, a more common usage of wildcards is in the parameter of a method. In this case, you really don't know what is being passed, but you do know that it is a super of a particular class.
So one final question on this if I may...
List<? super ShireHorse>myList2 = new ArrayList<Animal>();
myList2.add(new ShireHorse());
The code above works OK. In fact, I can replace new ArrayList<Animal>(); with new ArrayList<Object>; new ArrayList<Horse>; and they all compile, so what is the significance of my choice of object on the right-hand side of the equals...?
Of course they all compile, the actually type on the right hand side, fits the criteria of the type on the left hand side. As for "the significance of [your] choice of object on the right-hand side of the equals", you do know that they behave differently right?
Especially if List<? super ShireHorse>myList2 returns Objects anyway....
Not sure what you are asking here... Just because a List<? super ShireHorse> returns Objects when iterating, doesn't make it a List<Object> type. You can place Dog objects into a List<Object> -- which you can't do in a List<? super ShireHorse>.
Or are you thinking there is another way to declare it?
Henry
[ December 09, 2008: Message edited by: Henry Wong ]
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Why would you purposely use wildcards, when you know exactly what the collection is?
My question exactly!! In fact, that was my original question in this thread, as below.
Why does the compiler accept this notation? Could this List ever be anything other than type Horse?
Why does the compiler accept this notation at all? Why doesn't it just say, come on, you know what the collection type is, you just told me?
As for the rest of it, everything is clear, thanks.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Originally posted by Paul Kemp:
Why does the compiler accept this notation at all? Why doesn't it just say, come on, you know what the collection type is, you just told me?
You are taking my response out of context. I actually explain why in the sentence that you didn't quote. The compiler allows this notation because there are cases, where it doesn't know what type the collection is... Take an example from this very topic.
This method is written to handle a list of elements, of an unknown type that is a super of Dog. In this case, you actually do not know what types your method will be called with. But you do know that the compiler will type check it, to make sure it is not called with a list of Strings, or anything else that is not a super class of Dog.
Henry
[ December 09, 2008: Message edited by: Henry Wong ]
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
<? super Horse> syntex has been made. This syntax is made to avoid situations that arose with Array in ArrayStoreException.
It has been made actually to restrice containers for ex: ArrayList<Animal>, ArrayList<Cat>. So that we cannot pass wrong container. Compiler will force use to pass right container.
If you declare reference List<? super Horse>, then you cannot pass the container ArrayList<Cat> that can take cat . You have to pass minimum container that could take Horse, like ArrayList<Horse>, ArrayList<Animal>, ArrayList<Object> that can atleast take Horse and its subclasses.
[ December 09, 2008: Message edited by: Punit Singh ]
SCJP 6
| Is this the real life? Is this just fantasy? Is this a tiny ad? The new gardening playing cards kickstarter is now live! https://www.kickstarter.com/projects/paulwheaton/garden-cards |








