簡體   English   中英

為什么List接口的lastIndexOf()方法接受Object作為參數而不接受E?

[英]Why does lastIndexOf() method of List interface accepts Object as parameter and not E?

List接口的lastIndexOf()方法接受一個Object類型的參數。

但是, add()方法接受類型E的參數(這是創建列表時定義的List的泛型類型)。由於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
}
}

在第1行和第2行,我將不兼容的對象傳遞給了String類型的List。 但是,我得到的輸出是:

5
-1
-1

我沒有ClassCastException。

如果lastIndexOf()方法正在接受類型E的對象而不是對象類型的對象,則只能在編譯時才禁止這樣做。 為什么不這樣做?

Java創建者必須考慮過如果接受E(而不是Object)可能會發生的一些問題。 這會帶來什么危害?

您不需要E類型-請記住,泛型只是用於類型轉換的類型檢查糖,並且equals是在Object上定義的,因此您無需對項目進行強制轉換來確定它是否與其他類型相等。清單。 另外,請考慮有界通配符用法。 如果您的列表定義為List<? extends Foo> List<? extends Foo> ,您將無法獲取null以外的任何項目的lastIndexOf

出於同樣的原因,Collection.remove(Object o)具有相似的簽名。 有關更多詳細信息,請參見此問題

在方法中,像remove一樣,它將遍歷Array [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")

也可以在這里查看。 為什么Java Collections不能通用刪除方法? 另一個為什么Map.get(Object key)不是(完全)泛型的原因是什么

這是一個可能有幫助的示例。 請注意,如果以相同順序傳遞帶有相等元素的LinkedList<T> ,則ArrayList<T>使用的equals方法將返回true。 因此,如果您具有List<ArrayList<Integer>> ,則可以在其上調用lastIndexOf ,並傳遞LinkedList<Integer> ,以找到相等的ArrayList<Integer> ,這是有效的。 但是,如果lastIndexOf是按照您的描述方式定義的,則不可能實現。

lastIndexOf只關心equals()方法。 因此,采取任何措施都是很高興的,並且僅在底層的equals()方法執行時才會崩潰。

一種更安全的方式是定義一個接口“可以檢查是否與……相等”,該接口的工作方式類似於Comparable。 但這是很多工作的方式,並且不向后兼容。

考慮它的一種可能方法是由於泛型中的通配符。

想象一下,如果有,

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

(假設所有字符串都在list )。 如果List API具有List.lastIndexOf(E e) ,那么按照上面的示例,從字面上看,這會使它成為List.lastIndexOf(? extends Serializable)並且您實際上不能傳遞null以外的對象。

這就是為什么他們將Object作為參數類型。 應該只為lastIndexOf()搜索正確實現對象的equals()方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM