在数组中存储比较器对象

3

我已经为我的对象定义了4个比较器,像这样:

public static Comparator<mObject> comp0 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp1 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp2 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp4 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

现在我想创建一个包含4个比较器的数组,就像这样:
public final static Comparator<mObject>[] Object_comparators = { comp0,
        comp1,
        comp2,
        comp3};

但 Eclipse 在 {..} 之间的所有内容都会像错误一样被下划线标出。为什么会这样,我该如何解决?


请参阅以下链接:https://dev59.com/TkjSa4cB1Zd3GeqPChpp - Mark Elliot
2个回答

9

你不能创建一个具有参数化泛型类型的类数组。

如果你不介意失去类型安全性,你可以这样做:

Comparator[] list = new Comparator[4];

但我的首选策略是使用一个 List

List<Comparator<mObject>> list = Arrays.asList(comp0, comp1, comp2, comp3);

2
正如Mark Elliot所说,您不能在数组中使用泛型类型。这是由于类型擦除,而数组在运行时有其类型已知。由于类型擦除,泛型类型在运行时永远不会被知晓。这意味着泛型仅在编译时有用,并且通过一些技巧,您可以将Animal对象插入到List中。
顺便说一下,您无法声明匿名数组的创建而不指定数组的类型,因为对于数组类型没有类型擦除。
因此,不允许使用泛型类型创建数组,并可能导致一些意想不到的行为。
想想看:如果您创建了一个汽车数组(Car []),那么您可以将其强制转换为Object []。这并不意味着您可以将对象放入该数组中,因为数组的类型仍然在运行时已知。如果您尝试将狗放入该数组中,您将得到ArrayStoreException。
现在,如果我们创建了一个Car[]数组呢?您仍然可以将其转换为Object[]。它的工作方式类似于Car[]数组,但在这种情况下,当您将其转换为Object[]时,您将能够在运行时放置Car类型的对象,因为泛型类型未知!
我认为Java防止我们进行这样的行为。
但是,您仍然可以使用泛型引用数组!
public static void main(String[] args) {

    Comparator<String> NORMAL = new Comparator<String>() {
        @Override
        public int compare(String s, String s1) {
            return s.compareTo(s1);
        }
    };

    Comparator<String> REVERSE = new Comparator<String>() {
        @Override
        public int compare(String s, String s1) {
            return - s.compareTo(s1);
        }
    };

    Comparator<String>[] comparators = new Comparator[] {NORMAL,REVERSE};

    List<String> strings = Arrays.asList("f","d","c","a","e","b");

    TreeSet<String> normalSet = new TreeSet<String>(comparators[0]);
    normalSet.addAll(strings);
    for ( String s : normalSet ) {
        System.out.println("normal : " + s);
    }

    TreeSet<String> reverseSet = new TreeSet<String>(comparators[1]);
    reverseSet.addAll(strings);
    for ( String s : reverseSet ) {
        System.out.println("reverse : " + s);
    }

}

生成输出:

normal : a
normal : b
normal : c
normal : d
normal : e
normal : f

reverse : f
reverse : e
reverse : d
reverse : c
reverse : b
reverse : a

所以你可以使用带有泛型的数组,但Java似乎阻止你这样做。
我想这是因为最初的数组合同可能是这样的:
如果您创建类型为X的数组,则永远无法将任何非X的内容放入其中。如果尝试,将会收到ArrayStoreException异常。
因此,允许带有泛型的数组创建将导致不同的规则,如下所示:
如果您创建类型为X的数组,则永远无法放置任何非X的内容。如果尝试,将会收到ArrayStoreException异常。但是,您可以添加X和X对象!
正如我之前的代码所示,我们无法创建带有泛型的数组,但我们可以创建不带泛型的数组,并将其用作带有泛型的数组。
Comparator<String>[] comparators = new Comparator[] {NORMAL,REVERSE};

我想这是Java告诉我们的一种方式:“如果你知道自己在做什么,那么可以做到。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接