Why does the lastIndexOf () method of the List interface accept an object as a parameter, and not E?

The lastIndexOf () method of the List interface accepts a parameter that is of type Object.

However, the add () method accepts a parameter of type E (which is the general type of the list that was defined at the time the list was created) Since add () accepts only E, this prevents the developer (or user) from adding any incompatible object to the list at compile time.

Now, the Java doc says that lastIndexOf () can throw a ClassCastException if the passed object is incompatible. However, when I run the following code in Eclipse Helios, I get no exception: -

package scjp.collection.list; import java.util.ArrayList; import java.util.List; public class LastIndexOf { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("some"); list.add("thing"); list.add("at"); list.add("last"); list.add("and"); list.add("at"); list.add("again"); System.out.println(list.lastIndexOf("at")); System.out.println(list.lastIndexOf(10)); // # 1 System.out.println(list.lastIndexOf(new LastIndexOf())); // # 2 } } 

In Line 1 and Line 2, I passed incompatible objects to my List, which is of type String. However, the output I get is: -

 5 -1 -1 

I am not getting a ClassCastException.

If the lastIndexOf () method accepted objects of type E rather than objects of type Object, this would be prevented only at compile time. Why is this not done?

The creators of Java should have thought of some problem that might arise if it accepts E (and not an object). What harm would it be?

+7
source share
6 answers

Here is an example that might help. Note that the equals method used by ArrayList<T> will return true if passed a LinkedList<T> with equal elements in the same order. So, if you have a List<ArrayList<Integer>> , it would be correct to call lastIndexOf on it, passing the LinkedList<Integer> to find the equal ArrayList<Integer> . But if lastIndexOf were defined as you described, that would be impossible.

+1
source

You donโ€™t need type E - remember that generics are just type-tested sugar for casts, and equals is defined on Object , so you donโ€™t need to throw an element to find if it is equal to the other elements in the list. Also consider the limited use of templates. If your list has been defined as List<? extends Foo> List<? extends Foo> , you cannot get lastIndexOf for any item except null .

+2
source

For the same reasons that Collection.remove (Object o) has a similar signature. See this question for more details.

+2
source

In methods such as remove , it will intersect the Array [E] method and try equals () for each object, and then delete by index if it is found. lastIndexOf is the same as below.

 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) **if (o.equals(elementData[i]))** return i; } return -1; } 

So, if the LastIndexOf class defines its own equals function, and you make it equal to the "at" string, then according to the java specification, the value of lastIndexOf(new LastIndexOf()) should return the value as lastIndexOf("at") .

Also check here. Why doesnโ€™t Java Collection remove common methods? Another What are the reasons why Map.get (Object key) is not (fully) general

+2
source

lastIndexOf only cares about the equals () method. Therefore, he is happy to take something and will only explode if the basicals method is equal to ().

A safer way to do this would be to define a โ€œcan be tested for equality withโ€ interface, which would be a bit like Comparable. But so much work, not backward compatibility.

0
source

One possible way to think about this is because of the wildcards in Generics.

Imagine if you,

 List<? extends Serializable> list = new ArrayList<> extends Serializable>(); 

(Assume all lines are in list ). If the list API had List.lastIndexOf(E e) , then literally, with our example above, this would make it List.lastIndexOf(? extends Serializable) , and you could not pass an object other than null .

That's why they set Object as the type of parameter. You just need to implement the equals() method of the object to search for lastIndexOf() .

-one
source

All Articles