Java 为什么List接口的lastIndexOf()方法接受对象作为参数而不是E?
列表接口的方法接受类型为Object的参数 但是,该方法接受类型为E的参数(这是在创建列表时定义的列表的泛型类型) 由于add()只接受E,这将防止开发人员(或用户)在编译时将任何不兼容的对象添加到列表中 现在,Java文档说,如果传递的对象不兼容,lastIndexOf()可以抛出ClassCastException。但是,当我在Eclipse Helios中运行以下代码时,我没有得到任何异常:-Java 为什么List接口的lastIndexOf()方法接受对象作为参数而不是E?,java,list,generics,Java,List,Generics,列表接口的方法接受类型为Object的参数 但是,该方法接受类型为E的参数(这是在创建列表时定义的列表的泛型类型) 由于add()只接受E,这将防止开发人员(或用户)在编译时将任何不兼容的对象添加到列表中 现在,Java文档说,如果传递的对象不兼容,lastIndexOf()可以抛出ClassCastException。但是,当我在Eclipse Helios中运行以下代码时,我没有得到任何异常:- package scjp.collection.list; import java.util.
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
}
}
我没有例外
如果lastIndexOf()方法接受的是E类型的对象而不是Object类型的对象,那么这只能在编译时防止。为什么不这样做
Java创建者一定认为如果接受E(而不是Object),可能会出现一些问题。这会有什么害处呢?您不需要
E
类型——请记住,泛型只是用于强制转换的类型检查,而equals
是在对象上定义的,因此您不需要强制转换该项来确定它是否与列表中的其他项相等。此外,考虑有界通配符使用。如果您的列表被定义为list,那么下面的示例可能会有所帮助。请注意,ArrayList
使用的equals
方法如果以相同的顺序传递LinkedList
,将返回true。因此,如果您有一个列表
,可以通过传递一个链接列表
,在该列表上调用lastIndexOf
,以找到一个相等的数组列表
。但是,如果按您描述的方式定义了lastIndexOf
,这是不可能的。原因与Collection.remove(对象o)具有类似的签名相同。有关更多详细信息,请参阅。一种可能的方法是考虑泛型中的通配符
想象一下如果你有
List<? extends Serializable> list = new ArrayList<> extends Serializable>();
List在方法中,如remove
,它将遍历数组[E]并对每个对象尝试equals()方法,然后按索引删除(如果找到)。lastIndexOf
与下面相同
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;
}
因此,如果LastIndexOf类定义了自己的equals函数,并将其设置为字符串“at”,那么根据java规范,LastIndexOf(new LastIndexOf())
应该返回值为LastIndexOf(“at”)
也可以在这里查看。
另一个
lastIndexOf只关心equals()方法。因此,它很乐意接受任何东西,并且只有在底层的equals()方法这样做的情况下才会爆炸
一种更为类型安全的方法是定义一个接口“可以检查是否与相等”,它的工作方式有点类似于Comparable。但这是一种需要做大量工作的方式,而且不向后兼容。请看。我们清楚地提到,参数是一个对象,现在异常是trown。“这将使它成为List.lastIndexOf(?extends Serializable))并且您不能真正传递除null以外的对象。”这是不好的,因为?如果只有同一类的对象可以相等,那么您提到的限制对于强制类型安全确实是必要的——如果我们不知道列表中的元素是什么类,那么我们就无法安全地搜索元素,因为该元素可能不正确type@newacct,很糟糕,因为编译器不知道在不使用java的情况下添加String
或Integer
是否安全。Java不知道对象是否是您提供的超类型。因此,编译器可能不接受参数,因为它不是类型安全的。因此,我们需要允许任何类型(对象
)并进行相等比较。我不理解您的回答。我是说,参数是typeObject
的唯一原因是不同类的对象可以相等。如果假设Java是以这样一种方式生成的,即类的equals方法只能接受相同类型的对象,那么lastIndexOf()
确实应该接受类型E
,原因与add()
接受类型E
——否则是不安全的,我使用了为什么1)由于通配符的类型安全约束,在语法上(编译方面)使用泛型是明智的,而且equals()
在泛型通配符方面也不起作用。
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;
}