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

正如我已经定义了自己的 Number 类型的比较器,但是当我向其中添加任何其他字符串时,它并没有给我任何例外。它工作正常。我得到的输出为

[1, 1.4, 1, 1a]

任何人都可以解释为什么会这样。

4

3 回答 3

17

问题是一些不良做法的混合:

  • 您正在使用原始类型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 Comparatorfor aTreeSet用于排序,而不是用于抛出 CCE。由于您的比较器旨在返回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 回答