2012-01-31 8 views
7

ListインターフェイスのlastIndexOf()メソッドは、Object型のパラメータを受け入れます。ListインターフェイスのlastIndexOf()メソッドが、Objectをパラメータとして受け取り、Eを受け付けないのはなぜですか?

しかし、add()方法は、Eを受け入れる)(ADDので(リストの作成時に定義されたリストの一般的な型である)タイプEのパラメータ を受け付け、これは(現像を防止コンパイル時に互換性のないオブジェクトをリストに追加することができます。

Javaのdocは、渡されたオブジェクトが互換性がない場合、lastIndexOf()がClassCastExceptionをスローできることを示しています。私は、Eclipse Heliosの中で、次のコードを実行したときしかし、私は、任意の例外を得ることはありません: - 1行目と2行目

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 
} 
} 

は、私はString型である私のリストに互換性のないオブジェクトを渡しました。 はしかし、私が手に出力されます: -

5 
-1 
-1 

私はClassCastExceptionが取得していません。

lastIndexOf()メソッドがObject型のオブジェクトではなくE型のオブジェクトを受け入れていた場合、これはコンパイル時にのみ防止されていました。なぜこれはしないのですか?

Javaクリエイターは、E(オブジェクトではない)を受け入れる場合に発生する可能性のある問題を考えていたに違いありません。それはどんな害でしょうか?

+1

http://docs.oracle.com/javase/1.5.0/docs/api/index.htmlを参照してください。引数がObjectであり、例外がスローされることは明らかです。 – xyz

答えて

1

これは参考になる例です。 ArrayList<T>によって使用されるequalsメソッドは、等しい順序で同じ要素を持つLinkedList<T>を渡すとtrueを返します。したがって、List<ArrayList<Integer>>をお持ちの場合は、をLinkedList<Integer>に渡して、ArrayList<Integer>と同じものを見つけることが有効です。しかし、lastIndexOfがあなたの方法で定義されていれば、これは不可能です。

2

あなたはEタイプは必要ありません - ジェネリック医薬品は、キャストのためだけ入力し、確認の砂糖であることを忘れないでください、とequalsObjectに定義されているので、それに等しいかどうかを調べるために項目をキャストする必要はありませんがリスト内の他の項目また、有界ワイルドカードの使用を検討してください。あなたのリストがList<? extends Foo>と定義されている場合、null以外のアイテムにはlastIndexOfを取得できません。

2

同じ理由から、Collection.remove(Object o)にも同様の署名があります。詳細はthis questionを参照してください。

-1

考えられる方法の1つは、Genericsのワイルドカードが原因です。

は、あなたが持っていた場合、

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

は、(すべての文字列がlistであると仮定すると)想像してみてください。 List APIにList.lastIndexOf(E e)があった場合、上の例では文字通りList.lastIndexOf(? extends Serializable)になり、null以外のオブジェクトを渡すことはできませんでした。

これは、パラメータタイプとしてObjectを指定した理由です。 lastIndexOf()検索では、オブジェクトのequals()メソッドを正しく実装するだけです。

+0

"これにより、List.lastIndexOf(?extends Serializable)になり、null以外のオブジェクトを実際に渡すことができなくなります。そしてこれは悪いですから?同じクラスのオブジェクトだけが等しい場合、型の安全性を強制するためには、あなたが言及している制限が本当に必要です。リストの要素がどのクラスであるかわからない場合は、その要素が正しい型でない可能性があるので、要素を安全に検索してください。 – newacct

+0

@newacct、コンパイラはjavaを使わずに 'String'または' Integer'を追加するのが安全かどうかを知りませんので、悪いです([wildcard capture] http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf)。 Javaは、オブジェクトが提供するスーパータイプであるかどうかを認識しません。したがって、コンパイラはタイプセーフなので引数を受け付けない可能性があります。したがって、任意の型( 'Object')を許可し、等価比較を行う必要があります。 –

+0

私はあなたの返信を理解していません。私は、引数がObject型である*唯一の理由は、異なるクラスのオブジェクトが等しいことができるためです。クラスのequalsメソッドが同じ型のオブジェクトしか取ることができないような方法でJavaが作成されたと仮定した場合、 'lastIndexOf()'は 'add()'が 'それ以外の場合は安全ではありません。 – newacct

2

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クラスは、独自に定義する場合、関数に等しく、そしてあなたはそれが「で」文字列に等しい行い、その後、Javaの仕様に応じてlastIndexOf(new LastIndexOf())lastIndexOf("at")として値を返す必要があります。

こちらもチェックしてください。 Why aren't Java Collections remove methods generic? もう一つWhat are the reasons why Map.get(Object key) is not (fully) generic

0

のlastIndexOfのみのequals()メソッドを気。だから、何かを取ってうれしいですし、基礎となるequals()メソッドが行う場合にのみ爆発します。

より安全な方法は、Comparableのように動作する「等価性があるかどうかを確認できます」というインターフェースを定義することでした。しかし、それは多くの作業に向いており、後方互換性はありません。

関連する問題