gpt4 book ai didi

java - Max element - Sun 的答案 VS 我的

转载 作者:搜寻专家 更新时间:2023-10-31 19:46:24 27 4
gpt4 key购买 nike

在阅读了 Sun 关于泛型的文档后,我转到了 http://docs.oracle.com/javase/tutorial/java/generics/QandE/generics-questions.html 的问答部分。 .

对于 Q8 -

Write a generic method to find the maximal element in the range [begin, end) of a list.

我写的代码是:

private static <T extends Comparable<T>> T max(List<T> l, int i, int j) {
List<T> sublist = l.subList(i, j);
System.out.println("Sublist "+sublist);
int c = 0;T max = null;
for(T elem: sublist) {
if(c == 0 || max.compareTo(elem) < 0) {
max = elem;
} ++c;
}
return max;
}

Sun 的回答是:

public static <T extends Object & Comparable<? super T>>

T max(List<? extends T> list, int begin, int end) {

T maxElem = list.get(begin);

for (++begin; begin < end; ++begin)
if (maxElem.compareTo(list.get(begin)) < 0)
maxElem = list.get(begin);
return maxElem;
}

有人可以举例说明 Sun 的版本比我的好吗?

EDIT: I want to compare the efficiency of the 2 solutions mainly on the basis of Type parameters/bounds used in the method declaration and not the logic e.g. in what situation(s) Sun's version is better for a caller of the function? Basically I don't understand why you need <T extends Object & Comparable<? super T> and List<? extends T> as used by Sun and not what I have used.

非常感谢一个例子,因为我已经被理论淹没了。 (抱歉,如果这听起来很粗鲁,但我不是故意的)。

提前致谢,穆斯塔法

最佳答案

这里有两个独立的泛型问题。

为什么要使用交叉路口类型?

也就是为什么解法要用T extends Object & Comparable<T>而不是更直接的 T extends Comparable<T> ? (我在本节中删除了通配符;我将在下面介绍它们。)

我不相信Object & Comparable<T>Comparable<T> 有什么不同在类型系统中,因为每个对象都扩展了 Object .也就是说,没有类型 T延伸 Comparable<T>也不会扩展 Object & Comparable<T> .

不过还是有区别的。交集类型删除到交集的第一个组件,因此 T extends Object & Comparable<T>删除到 ObjectT extends Comparable<T>删除到 Comparable .考虑 max 的两个替代声明方法:

<T extends Comparable<T>> T max1(List<T> list) { ... }

<T extends Object & Comparable<T>> T max2(List<T> list) { ... }

如果使用 javap -s 转储这些方法的签名您可以看到显示已删除类型的内部签名:

<T extends java/lang/Comparable<T>> T max1(java.util.List<T>);
Signature: (Ljava/util/List;)Ljava/lang/Comparable;

<T extends java/lang/Object & java/lang/Comparable<T>> T max2(java.util.List<T>);
Signature: (Ljava/util/List;)Ljava/lang/Object;

谁在乎被删除的类型? JVM 可以。 JVM 根据参数类型和返回类型 的匹配来查找方法。因此,删除的返回类型可能很重要。

事实上,从二进制兼容性的角度来看,它很重要。在 Java SE 5 之前,当引入泛型时,Collections.max方法被声明并具有被删除的签名如下:

public static Object max(Collection coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Object;

在 Java SE 5 及更高版本中,声明和删除签名是:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Object;

重要的是,删除后的签名相同

如果不是使用交集类型声明 Java SE 5 声明,它将如下所示:

public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Comparable;

这将是二进制不兼容。针对旧版本的 JDK 编译的二进制文件将引用 max 的版本返回 Object .如果使用此替代的、不兼容的声明针对 JDK 运行,max 的唯一版本会返回 Comparable相反,导致 NoSuchMethodError在链接时抛出。

因此,使用<T extends Object & Comparable<T>>真正是为了控制这个声明的删除,这是出于二进制兼容性的考虑。该教程在这一点上似乎有些误导。 Collections.max的实际申报在 Java SE 中,这种方式是为了二进制兼容性。但是,如果您是第一次声明此方法,我认为以这种方式使用交集类型不会有用。

为什么要在声明中使用通配符?

也就是说,代替:

static <T extends Comparable<T>> T max(List<T> list)

为什么要使用通配符:

static <T extends Comparable<? super T>> T max(List<? extends T> list)

这里,为了在存在子类型的情况下更灵活地使用方法,通配符是必要的。请考虑以下事项:

class A implements Comparable<A> { ... }

class B extends A { }

List<B> bList = ...;
B bMax = max(bList);

如果使用非通配符声明,则不会有 T那匹配。为了使这项工作,Comparable<? super T>有必要的。这允许 T被推断为B一切正常。

我必须承认我没能找到一个例子来说明为什么 List<? extends T>在这种情况下是必需的。如果简单地声明参数 List<T>,则此示例工作正常.可能是List<? extends T>用于文档目的,指示元素仅从列表中检索,并且列表未被修改。 (有关这方面的更多信息,请参阅 Bloch 的 Effective Java,在他讨论 PECS 的泛型章节中——“Producer Extends,Consumer Super”;或 Naftalin 和 Wadler 的 Java Generics and Collections 他们讨论“放置和获取原则”的地方。)


链接:

Why is T bound by Object in the Collections.max() signature?

Angelika Langer's FAQ entry

Java Generics: What is PECS?

Why do we need bounded wilcard in Collections.max() method

关于java - Max element - Sun 的答案 VS 我的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20276668/

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