代码之家  ›  专栏  ›  技术社区  ›  Happo

Java通用比较器未检查警告

  •  2
  • Happo  · 技术社区  · 11 年前

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

    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的通用数组。

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

    2 回复  |  直到 11 年前
        1
  •  4
  •   Jon Skeet    11 年前

    我的通用语法有问题吗?

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

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

    幸运的是,你甚至不需要自己写这篇文章——你可以使用 Guava 要么与 ComparisonChain Ordering.compound 。请注意 compound 哪个是 喜欢 您的数组版本,但需要 Iterable<? extends Comparator<? super T>> 参数-哪个 安全

        2
  •  1
  •   newacct    11 年前

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

    重要的是要知道,只有当您依赖于 比较器 。如果你只需要迭代它的元素(就像你的方法所做的那样),那么它仍然是完全安全的。为了以这种方式表明您的函数是安全的,如果您使用的是Java 7+,请添加 @SafeVarargs 注释到您的方法,并且警告将停止。