gpt4 book ai didi

java - 了解 Java 中的 Collections.reverseOrder() 方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:18:25 26 4
gpt4 key购买 nike

考虑 sort 的重载定义之一方法来自 Array类:

public static <T> void sort(T[] a, Comparator<? super T> c)

逆序排列数组的常用方法是传递ComparatorCollections.reverseOrder() 返回作为此方法的第二个参数。

让我们看看Collections.reverseOrder()的实现来自 openjdk 7 的方法:

public static <T> Comparator<T> reverseOrder() {
return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
}

ReverseComparator类:

private static class ReverseComparator
implements Comparator<Comparable<Object>>, Serializable {

private static final long serialVersionUID = 7207038068494060240L;

static final ReverseComparator REVERSE_ORDER = new ReverseComparator();

public int compare(Comparable<Object> c1, Comparable<Object> c2) {
return c2.compareTo(c1);
}

private Object readResolve() { return reverseOrder(); }
}

我的问题是:为什么 Collections.reverseOrder()是通用的吗?为什么只是 ReverseComparator.REVERSE_ORDER无法返回?

当然,我们可以显式指定类型调用Collections.<T>reverseOrder() .但是相对于简单的 Collections.reverseOrder() 有什么好处呢?在这种情况下?

我在那里找到了一个相当有用的讨论:

How does Collections.reverseOrder() know what type parameter to use?

但它没有回答我的问题。

我也很感兴趣 sort方法使用 compare方法来自 ReverseComparator类(class)。正如我们所见compare采用 Comparable<Object> 的参数类型。如果我们对实现 Comparable<T> 的对象数组进行排序怎么办? , 其中T例如 Integer ?我们不能调用 compareComparable<Integer>原因Comparable<Integer>未转换为 Comparable<Object> .

最佳答案

why Collections.reverseOrder() is made to be generic?

此函数是通用的,因此您不必将结果转换为特定的 Comparable<T>类型。 (您可能会说您不在乎,因为您无论如何都不投它,在这种情况下,这告诉我们您没有启用足够的警告。)

why we can't simply return ReverseComparator.REVERSE_ORDER?

一个原因是因为ReverseComparator.REVERSE_ORDER是包私有(private)的,因此您无法从该包外部访问它。这反过来又引出了一个问题“为什么它是包私有(private)的?”好吧,主要是因为这满足了纯粹主义者,他们看到成员变量被直接访问时会畏缩,即使它们是最终的,但实际上在这种情况下我不会责怪他们,因为访问器在二进制级别提供前向兼容性,这可能是完全不必要的在应用程序代码中,但它在某种程度上成为语言运行时的必需品。和 ReverseComparator是 java 运行时的一部分。

但更重要的原因是因为Collections.reverseOrder()转换为 (Comparator<T>)为你,这样你就不必自己做。 (同样,如果您没有发现这方面的问题,那是因为您没有启用足够多的警告,这意味着您需要重新考虑您的做法。)

简而言之,如果您尝试执行以下操作:

Comparator<MyObject> myComparator = ReverseComparator.REVERSE_ORDER;

你会得到一个错误,因为这是一个无效的赋值。因此,您必须将其更改为:

Comparator<MyObject> myComparator = 
(Comparator<MyObject>)ReverseComparator.REVERSE_ORDER;

但是你会得到一个警告,因为这是一个未经检查的转换。所以你最终不得不这样做:

@SuppressWarnings( "unchecked" )
Comparator<MyObject> myComparator =
(Comparator<MyObject>)ReverseComparator.REVERSE_ORDER;

这是丑陋的。所以,Collections.reverseOrder()将您从中拯救出来,让您可以这样做:

Comparator<MyObject> myComparator = Collections.reverseOrder();

As we can see compare takes arguments of Comparable type. And what if we sort array of objects implementing Comparable, where T is for example Integer? We can't invoke compare with Comparable cause Comparable isn't casted to Comparable.

好的,我明白你真正的问题是什么了。欢迎来到 Java 泛型和类型删除的精彩世界。我会尝试解释,但一定要同时查找术语“类型删除”以充分理解这个概念。

在 Java 中,泛型是事后才引入的。出于这个原因,它们必须以这样一种方式实现,即泛型感知代码将向后兼容非泛型感知的旧代码。解决方案是一种称为类型删除的技巧,这基本上意味着通用信息在编译后被完全剥离。这意味着在字节码级别,Comparator<String>Comparator<Integer>Comparator是一回事。没有任何区别。这就是使 Java 运行时能够实现单个类的原因,该类充当任何对象的反向比较器。这不是真的 Comparator<Object> , 它是一个 Comparator<ANYTHING> , 因为它所做的只是反转比较的方向,所以它并不真正关心被比较对象的性质。

因此,在 Java 中,如果您真的知道自己在做什么,您可以自由地将泛型类的实例转换为同一类的实例,但使用不同的泛型参数。在这种情况下,java 运行时的创建者正在转换 Comparator<Object>Comparator<T> ,实际上稍后可能会分配给 Comparator<Integer> ,没关系。

虽然这个转换很棘手,因为编译器必须相信你真的知道你在做什么,所以默认情况下,编译器会在此类转换上发出“未经检查的赋值”警告,然后我们反过来表明我们发誓我们知道我们在用 @SuppressWarnings( "unchecked" ) 做什么注释。

Collections.reverseOrder()让您不必担心所有这些。

关于java - 了解 Java 中的 Collections.reverseOrder() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33965539/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com