Reputation: 1367
I have the following code segment:
public void reorder(int fromIndex, int toIndex) {
getElements().add(toIndex, getElements().remove(fromIndex));
}
Here, the method getElements
has the return type List<?>
. The remove
method has the return type ?
, and the add
method shows its arguments as int index, ? element
. So my assumption was, since the return type of remove
method and second argument of add
method are the same - ?
- the method call must succeed. But, I was wrong, the above code segment results in the error:
The method add(int, capture#17-of ?)
in the type List<capture#17-of ?>
is not applicable for the arguments (int, capture#18-of ?)
Here, I don't have any direct access to the list, and I don't know it's original type returned by getElements
method. All I want here is to remove the item at fromIndex
and put it at toIndex
. So, how do I achieve that? Also is there anything wrong with my understanding of the generics?
Upvotes: 2
Views: 1631
Reputation: 6191
No no no! Use capture:
public void reorder(int fromIndex, int toIndex) {
reorderWithCapture(getElements());
}
private <E> void reorderWithCapture(List<E> elements) {
elements.add(toIndex, elements.remove(fromIndex));
}
Upvotes: 4
Reputation: 116306
The wildcard ?
means any (unknown) type, not one specific type. So the compiler can't verify that the any type used in the remove
call is the same as the any type used in the getElements
and add
calls. This is seen from the error message, where the former is described as capture#18-of ?
while the latter is capture#17-of ?
. These are seen as two different, unrelated types by the compiler.
Since you apparently can't modify the definition of these methods (although they definitely look fishy based on your description), the least worst option here is probably what @Marko suggests: separate the two steps of the process and use a temp variable with a concrete type parameter (Object
) to make the compiler happy.
Upvotes: 1
Reputation: 200296
Just add a cast that makes that ?
concrete:
public void reorder(int fromIndex, int toIndex) {
final List<Object> els = (List<Object>)getElements();
els.add(toIndex, els.remove(fromIndex));
}
Since you are just rearranging elements within the list, this will never cause any trouble. But I must say there's something wrong with the design if you are seeing that kind of return value.
Upvotes: 2