2

我写了一个帮助方法来将多个比较器组合成一个:

public static <T> Comparator<T> createComparatorChain( final Comparator<T>... comparators )
{
    return new Comparator<T>()
    {
        public int compare( T lhs, T rhs )
        {
            for( Comparator<T> comparator : comparators )
            {
                int order = comparator.compare( lhs, rhs );
                if( order != 0 )
                {
                    return order;
                }
            }
            return 0;
        }   
    };
}

但是如果我使用这种方法,那么我会收到一个未经检查的警告:

Collections.<File>sort( list, ComparatorUtils.<File>createComparatorChain( BY_FILE_DIRECTORY, BY_FILE_NAME ) );

类型安全:为 varargs 参数创建一个通用的 Comparator 数组。

我的通用语法有问题吗?谁能帮我。

4

2 回答 2

4

我的通用语法有问题吗?

不,这只是 Java 泛型如何实现的另一个问题。基本上,数组和泛型类型不能很好地结合在一起。有关更多详细信息,请参阅Java 泛型常见问题解答

在这种特殊情况下,我不是从数组构建链,而是从几个链接在一起的比较器构建链 - 每个比较器都知道具有较高优先级的比较器和当前较低优先级的比较器。这避免了数组。每个比较器只要求其父级执行比较,如果结果非零则直接返回结果,或者执行自己的比较,否则返回结果。“顶部”比较器没有父级,因此只执行自己的比较。

幸运的是,您甚至不需要自己编写 - 您可以将GuavaComparisonChain或一起使用Ordering.compound。请注意,其中的重载compound类似于的数组版本,但需要一个Iterable<? extends Comparator<? super T>>参数 - 这安全的。

于 2013-04-12T06:14:14.000 回答
1

这是泛型和可变参数的经典问题。长话短说,这是因为可变参数实际上是数组的语法糖。例如,在这种情况下,comparators有 type Comparator<T>[]。在调用站点,编译器会创建一个正确类型的数组。当然,除了你可能知道的,Java 不允许你这样做new Comparator<File>[],所以编译器会这样做new Comparator<?>[]并给你一个警告。

重要的是要知道“不安全”仅在您依赖于comparators. 如果您只需要遍历它的元素(就像您的方法所做的那样),那么它仍然是完全安全的。为了表明您的函数以这种方式是安全的,如果您使用的是 Java 7+,@SafeVarargs请在您的方法中添加注释,警告将停止。

于 2013-04-12T09:44:11.393 回答