Because the remove(Object element); method already existed before generics were added to Java (in Java 5). For backward compatibility reasons, the old method that takes an Object has been preserved. If Java would have had generics from the beginning, it wouldn't have had this method that takes an Object instead of an E.
Jesper de Jong wrote:Because the remove(Object element); method already existed before generics were added to Java (in Java 5)...
@Kalpana: And just to add to what Jesper said, there are other examples too, such as Map.get().
In practise, these methods don't violate type safety too much, since what they do relies on finding the passed object in the collection (which won't be the case if it's the wrong type). They are also documented to optionally throw ClassCastException if the passed type is incompatible.
Perhaps they'll add a delete(E element) method at some point, but I don't see any burning need for it.
Bats fly at night, 'cause they aren't we. And if we tried, we'd hit a tree -- Ogden Nash (or should've been).
Articles by Winston can be found here
They can't add new methods to any existing interfaces, or it would break all implementations by other developers. This actually is already the case with JDBC. PreparedStatement, ResultSet and a few other interfaces have received extra methods in Java 6 that will not be implemented by older drivers. Perhaps the JDBC framework has solved this by catching errors and transforming them in SQLExceptions (e.g. SQLFeatureNotSupportedException), but it's also possible that you get a NoSuchMethodError instead (I haven't tested this yet). Perfect.
However, as Winston said, there is no need for a method like that. remove accepts any object as its argument which mean that a delete(E) method would do exactly the same but with some extra compiler checking. During runtime the two would be equivalent since type erasure would turn delete(E) into delete(Object).
The method takes an Object for greater flexibility. Say we have a variable:
List<? extends Number> numbers = new ArrayList<Integer>();
If the remove method took a generic type, we could not use it to remove anything from the numbers list. After all, numbers isn't aware of what the exact type argument is.
Since the remove takes an Object, we can try to remove anything from the list referenced by numbers. If the list doesn't contain the value, nothing happens.
Adding the wrong type to a list would cause great problems at runtime. That's why a compiler check is important. Removing a wrong type from a list does nothing, so checking is unnecessary.
The mind is a strange and wonderful thing. I'm not sure that it will ever be able to figure itself out, everything else, maybe. From the atom to the universe, everything, except itself.
Joined: Jan 05, 2012
@All : Thanks for the explanation.
For my understanding, what was the method definition of add before Generics were added in Java 5. Was it void add(Object element)? If so, when add(Object element) is rewritten as add(E element), why not remove(Object element) is rewritten?