Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么List接口的lastIndexOf()方法接受对象作为参数而不是E?_Java_List_Generics - Fatal编程技术网

Java 为什么List接口的lastIndexOf()方法接受对象作为参数而不是E?

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.

列表接口的方法接受类型为Object的参数

但是,该方法接受类型为E的参数(这是在创建列表时定义的列表的泛型类型) 由于add()只接受E,这将防止开发人员(或用户)在编译时将任何不兼容的对象添加到列表中

现在,Java文档说,如果传递的对象不兼容,lastIndexOf()可以抛出ClassCastException。但是,当我在Eclipse Helios中运行以下代码时,我没有得到任何异常:-

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不知道对象是否是您提供的超类型。因此,编译器可能不接受参数,因为它不是类型安全的。因此,我们需要允许任何类型(
对象
)并进行相等比较。我不理解您的回答。我是说,参数是type
Object
的唯一原因是不同类的对象可以相等。如果假设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;
}