I have an assignment to implement my own version of Collections.fill() and Collections.reverse(). The algorithms are simple enough, but I’m getting a little bit lost in the generics involved, specifically when I need to do casting.
My original idea is something like:
public static void reverse(List<?> a_list) {
int list_size = a_list.size();
ListIterator<?> left_to_right = a_list.listIterator();
ListIterator<?> right_to_left = a_list.listIterator(list_size);
? temp_variable;
// ..doing some stuff
right_to_left.set(temp_variable);
}
But of course I can’t declare the temp as type “?”. Declaring as “Object temp_variable” makes sense, but then the call to set(temp_variable) at the end won’t work (since the ListIterator won’t take Object — because the list is likely not type List<Object>).
It makes sense to me, then to declare temp as an Object, and cast the ListIterators:
ListIterator<Object> left_to_right =
(ListIterator<Object>) a_list.listIterator();
ListIterator<Object> right_to_left =
(ListIterator<Object>) a_list.listIterator(list_size);
The compiler gives me unchecked cast warnings when I do this, but I can’t think of how this would break, given my implementation. Is there any danger in doing this?
Then in Collections.fill(), I originally wanted to do something like:
public static <E> void fill(List<? super E> a_list, E an_object) {
ListIterator<E> an_iterator = (ListIterator<E>) a_list.listIterator();
// ..doing some stuff
an_iterator.set(an_object);
}
This gives an unchecked cast warning, too. And thinking about it more, even though I still get a warning, would it be safer to do a cast like:
ListIterator<Object> an_iterator = (ListIterator<Object>)a_list.listIterator();
If the generic type of the list is actually a superclass of E, it should be safer to cast to a ListIterator for a List of Objects, and not to a ListIterator for a subclass of the list’s generic type, shouldn’t it?
Any advice would be appreciated…I don’t think our instructor wanted us to get this involved, but I’d like to understand generics better.
Don’t cast, and don’t use
?. Use type-parameterized methods; something like this.