2017-12-09 5 views
1

は、次のコードを考えてみましょう:Javaでは、同じ型のコレクションは空になりますが、異なる型パラメータは常に等しくなりますか?

List<String> list1 = new ArrayList<>(); 
    List<Integer> list2 = new ArrayList<>(); 
    assertThat(list1.equals(list2), is(true)); 

アサーションが成功します。

確かに、私の知る限り理解し、そこequals方法は、この2つを区別するための、Javaの方法は、型消去(すなわち実際の型引数は、実行時のために、原因ではありませんStringIntegerしかアクセスできますコンパイル時には実行時には実行されません)。 そして、比較できる要素がないので、equalsはtrueを返す必要があります。そして、この考え方によって、これはすべてのコレクションにとって真実でなければなりません。

質問には次のようなものがあります:私の思考プロセスは正しいのですか、何か不足していますか? これはが明示的にタイプを通過することなく達成することが可能であるタイプが明示的に保存であれば(私は元気です:

EDITは

@qqilihqは、次の質問を促した、優れたanswerを与えました何とか、ユーザーだけがそれを渡す必要はありません)

私は次のように試みましたが、動作しませんでした(タイプ消去のためだと思います):

public TypedList(List<T> delegate) { 
     this.delegate = Objects.requireNonNull(delegate); 
     this.type = (Class<T>) delegate.getClass(); 
    } 

しかし、おそらくあなたはこれに類似したことをすることができますか? this.type = T

答えて

3

あなたが述べているように、タイプ情報は、与えられた例では実行時に失われます。しかし、コメントにあなたの質問について:

カウンタの例、つまり、異なるジェネリックタイプの2つの空のインスタンスが等しく扱われないコレクションも表示できますか?

あなたはもちろん、独自のCollectionを実装することができたを考慮にequals方法で型情報を取るん。あなたが原因述べた種類の消去に明示的にタイプを格納する必要があります

static final class TypedList<T> extends AbstractList<T> { 
    private final List<T> delegate; 
    private final Class<T> type; 

    public TypedList(List<T> delegate, Class<T> type) { 
     this.delegate = Objects.requireNonNull(delegate); 
     this.type = Objects.requireNonNull(type); 
    } 

    @Override 
    public T get(int index) { 
     return delegate.get(index); 
    } 

    @Override 
    public int size() { 
     return delegate.size(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (!super.equals(obj)) { 
      return false; 
     } 
     // Lists are equal, now additionally, check the type 
     TypedList<?> other = (TypedList<?>) obj; 
     return this.type.equals(other.type); 
    } 

    // hashCode omitted for brevity 
} 

注:ここでは任意のList周りTypedListラッパーを作成する非常に単純な例です。使用法:

List<String> list1 = new ArrayList<>(); 
List<Integer> list2 = new ArrayList<>(); 
System.out.println(list1.equals(list2)); // true 

list1 = new TypedList<>(list1, String.class); 
list2 = new TypedList<>(list2, Integer.class); 
System.out.println(list1.equals(list2)); // false 
+0

+1、それは私が考えなかった方法です。次の質問は、明示的に**型をパラメータとして渡すことなく、これを実現することが可能であることです(あなたが 'delegate'から何らかの形でそれを抽出すると問題ありません。この新しい詳細で質問を編集します。 – Attilio

+2

短くて否定的な答え:**明示的な型トークンなしで**不可能です。 'List 'は実行時に 'List'になりますので、情報はそこにはありません。 'Class 'の型は、これが「一流の市民」であるため、実行時に 'Class'であっても、供給された型情報(例えば' String.class'、 ...) – qqilihq

+0

サイドノート: 'java.util.Collections'はまったく同じ原理に従います。 'java.util.Collections.checkedList(List 、Class )' - 型引数を引数として明示的に渡す必要があります。 – qqilihq

0

実際には、コレクションインターフェイスを実装する個々のサブクラスがequals()メソッドをどのように処理するかによって異なります(このコンパイルは行われません)。反対のオブジェクトがリストされ、大きさは同じであり、すべての要素が対等であればそれだけでtrueを返す

public boolean equals(Object o) { 
    if (o == this) 
     return true; 
    if (!(o instanceof List)) 
     return false; 

    ListIterator<E> e1 = listIterator(); 
    ListIterator<?> e2 = ((List<?>) o).listIterator(); 
    while (e1.hasNext() && e2.hasNext()) { 
     E o1 = e1.next(); 
     Object o2 = e2.next(); 
     if (!(o1==null ? o2==null : o1.equals(o2))) 
      return false; 
    } 
    return !(e1.hasNext() || e2.hasNext()); 
} 

:ArrayListのために、実装は以下のようにどのAbstractListです。両方のListが空の場合、結果は真でなければなりません。

+0

です) 方法。"まあ、私が尋ねるのは、ArrayListがどうやってどうやって 'equals'を扱うのが本当に可能かどうかです。言い換えれば、カウンタの例、つまり、異なるジェネリック型の2つの空のインスタンスが等しく扱われないコレクションも表示できますか? – Attilio

0

ジェネリック医薬品は、コンパイル時に型チェックのために使用されています。あなたはこのようなArrayListを作成する場合

:彼らは空になっているので、

List<String> list1 = new ArrayList<>(); 
List<Integer> list2 = new ArrayList<>(); 
System.out.println(list1.equals(list2)); // result:true 

list1list2は等しくなります。 ArrayListは内部でObject[]を使用してArrayListのエントリを格納します。

あなたは配列リストにいくつかのエントリを追加した場合:

List<String> list1 = new ArrayList<>(); 
list1.add("A"); 

List<Integer> list2 = new ArrayList<>(); 
list2.add(1); 

System.out.println(list1.equals(list2)); // result: false 

をこれはfalseArrayListためのエントリを返します。それは本当に(コレクションインタフェースを実装sublcassが対等の処理方法を個々に依存し、」異なる

+0

Ajit:基本的には、どのように動作するのか、なぜ私の場合は、それが真実を返すのか理解しています。しかし、私はこのステートメントに同意しません "list1とlist2は空であるため等しいです"。私には、2つのリストは異なるタイプのものであるため、**概念的に**等しいことはできません。私はむしろ、これがJavaの短期間(または少なくとも特殊性)としてチェックできないという事実を見て、これを回避する方法があれば好奇心が強い。 – Attilio

関連する問題