From reading the K&B SCJP 5.0 cert book, the wildcard syntax is used to declare that a method can take a list of a generic type and its subtypes or supertypes, but it signifies that the list will not be modified. For instance,
is legal as long as inspectList() is not modifying the list. I think my statement is backed up by the summary in K&B on page 610 where it states that, "When using a wildcard, List<? extends Dog>, the collection can be accessed but not modified."
However, I am confused when I am looking at the Collections API. For instance, it declares reverse() located at: Class Collections,
public static void reverse(List<?> list)
Reverses the order of the elements in the specified list.
So, my confusion lies in the fact that this static method is not returning a new list. So, in order for it to reverse, isn't it modifying the original list? In other words, is it more accurate to say that the wildcard prevents adding and removing from a list? Or is reverse() modifying the iterator that would be returned so that it will iterate over the reverse order thus leaving the original list alone and unmodified?
p.s. it was a pain in the butt to change all the (, <, ), and >. This makes it real difficult to post a question about generics. I felt like giving up =( as I revisited my post 7 times to find the bad syntax.
There are certain things you can do with unbounded wildcards that you can't do with bounded wildcards. For example, you can create an array of generic type if the type parameter is an unbounded wildcard, but you can't create an array of generic type if the wildcard is bounded.
Also there is a link right under Options where you can turn smilies off.
Joined: Oct 02, 2006
So, I take it that the static reverse method is considered an unbounded wildcard since it is not qualified with super or extends. But I don't understand the tie in with what the reverse method is doing? Is it modifying the list that is passed in to the reverse()?
In the K&B book on pg 595, there is a code example as follows:
The explanation below says,
The problem is in the list.add() method within doInsert( . The <?> wildcard allows a list of ANY type to be passed to the method, but the add( method is not valid, for the reasons we explored earlier...
And previous to this text something similar is mentioned about List<?> and modification because the compiler can't guarantee an object of the correct type will be added to the list.
Essentially, what I want to know is if the original list is modified in any way when you sort it? It seems like this must be the case, but I want to know so I can put my collection in a new List whenever I sort. What is the best practice when it comes to sorting? My gut tells me that I would prefer to leave an original list unmodified and get a new sorted list in return. But I am not sure why I wouldn't just resort it with a new Comparator. However, there might be value in keeping the original order and that is what my gut does not feel good about since this information will be lost after I sort a list. This is in addition to knowing what the reverse() is doing under the covers as well as some of the other Collections static methods.
Well, the difference between adding a new Dog() and adding back elements that were already in the list is that the elements we add back were already in the list. There's no risk that you'll add a Dog to a List<Cat> by mistake because the fact that it's a List<Cat> already guarantees that all the objects in it are Cats (unless it's been mangled by some legacy code, but even then reversing the List isn't going to do any new harm that wasn't already done).
Joined: Feb 07, 2005
This is what happens in the Collections.reverse method.
Joined: Oct 02, 2006
Ok, it is time for a little self-deprecation, I must be dense. I understand that we are not doing harm if we are adding back the same elements to the list when they are being reversed, but one of the points from K&B about the wildcard is that it doesn't allow you to modfiy a list. Well, changing the order is a modification unless I am interpretting modification incorrectly. For one, wildcards and generics are a compile time check and are removed completely from runtime bytecode, so at runtime, everything is treated as an object. So, at runtime, the bytecode is not going to know whether it is adding a Cat or a Dog. Two, the code from the book on pg 595 is taking any List, but specifically adding a Dog to the list. That doesn't seem right as it is not guaranteeing that only objects of a certain type are added to the list. What is a List<Cat> is passed in to the doInsert. Then, the code is adding a Dog to it and that is a no-no.
But to the syntax of the the reverse method, where did you find this code for the reverse method? I don't see it in the javadocs. So, when a reverse is done, it is modifying the list with the swap method. And swapping indexes in a list must not be considered a modification as far as the compiler is concerned since it is not adding new Objects to the list, and rather it is swapping the elements that are already in the list. I guess when I read modifying in the text of K&B, my modifying has a wider scope and they really mean only adding to the list as a modification. Losing information like original order as lists maintain seems like a modification as information is lost. This makes sense.
So, it seems that if I want to maintain original order and not lose that information, I either extract this information into an Object that will maintain the original order information, or I create a new List with the contents of the original List and sort the new List. So, to continue with binarySearch, does the list have to be sorted before or can I hand in the sort as an argument with the binarySearch and everything will be taken care of? It seems that I need to hand in a pre-sorted list and the sort that was used to sort the list into binarySearch in order for it to work. Which means that I might as well sort the original List as keeping two lists is a pain in the butt. Hmmm, I think I read somewhere about some sort of indirection I can keep by creating a Row object that resolves to the list items. Then, I sort the Row objects which use the values from the original list they are tied to and use this sorted Row list. This will allow my original list to stay unmolested by methods like reverse =P.
Thanks for all the help. I think I better understand generics, I am still a little confused but it seems to be constained to add and probably insert, and I know how I will want to use lists with regards to the Collections API.