10

以下は私のコードです

class NumberComparator<Number> implements Comparator<Number> {
    public int compare(Number o1, Number o2) {
        return 1;
    }
}

public class Ex28 {
    public static void main(String[] args) {
        TreeSet set = new TreeSet(new NumberComparator<Number>());
        set.add(1);
        set.add(1.4f);
        set.add(1L);
        set.add("1a");
        System.out.println(set);
    }
}

数値型の独自のコンパレータを定義しましたが、それでも文字列である他のものを追加しているときは、例外は発生しません。それは単にうまく機能しています。私は次のように出力を取得しています

[1, 1.4, 1, 1a]

なぜそれが起こっているのか誰か説明してもらえますか?

4

3 に答える 3

17

問題は、いくつかの不適切な慣行が混在していることです。

  • のrawタイプを使用していますTreeSet
  • あなたNumberComparatorはジェネリックNumberです(タイプパラメータです)

ここで型パラメーターであるという事実Numberは、型消去は実際には実際のNumber型にキャストしないことを意味します。

コンパレータを次のように変更した場合:

class NumberComparator implements Comparator<Number> {
    public int compare(Number o1, Number o2) {
        return 1;
    }
}

とあなたの呼び出しコード:

TreeSet set = new TreeSet(new NumberComparator());

その後、私は例外を期待します。

さらに、生のタイプを使用しないようにコードを変更した場合:

TreeSet<Number> set = new TreeSet<Number>(new NumberComparator());

代わりに、コンパイル時エラーが発生します。

于 2012-08-17T08:05:23.650 に答える
3

aのAComparatorは、TreeSetCCEのスローではなく、注文に使用されます。コンパレータは1すべてを返すように設計されているため、順序が正しくないことを意味します。

これが、出力が順序付けられていない理由です。

のコンストラクタのドキュメントを必ずお読みくださいTreeSet

/**
 * Constructs a new, empty tree set, sorted according to the specified
 * comparator.  All elements inserted into the set must be <i>mutually
 * comparable</i> by the specified comparator: {@code comparator.compare(e1,
 * e2)} must not throw a {@code ClassCastException} for any elements
 * {@code e1} and {@code e2} in the set.  If the user attempts to add
 * an element to the set that violates this constraint, the
 * {@code add} call will throw a {@code ClassCastException}.
 *
 * @param comparator the comparator that will be used to order this set.
 *        If {@code null}, the {@linkplain Comparable natural
 *        ordering} of the elements will be used.
 */
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

Comparatorが設計されている要素以外の要素を追加しようとすると、がスローされることを明確に示していますClassCastExceptionジェネリックを使用しない場合は、を追加してこれをシミュレートできますString。ただし、ジェネリックスを使用する場合、これはコンパイル時の問題にすぎません。

その間、ジェネリックを一貫して使用する必要があります。

class NumberComparator<C> implements Comparator<C> {
    public int compare(C o1, C o2) {
        return 1; // change this logic
    }
}

Set<Number> set = new TreeSet<>(new NumberComparator<Number>());
于 2012-08-17T08:01:13.117 に答える
0

とにかく、コンパレータを以下のように定義すると、クラスキャスト例外が発生します:)

import java.util.Comparator;

class NumberComparator<Number> implements Comparator<java.lang.Number> {
public int compare(java.lang.Number o1, java.lang.Number o2) {


    return 1;
}
}
于 2012-08-17T08:28:38.587 に答える