gpt4 book ai didi

java - 通配符与通用方法

转载 作者:搜寻专家 更新时间:2023-10-30 20:01:45 24 4
gpt4 key购买 nike

以下打印范围内所有元素的方法之间是否存在任何实际差异?

public static void printA(Iterable<?> range)
{
for (Object o : range)
{
System.out.println(o);
}
}

public static <T> void printB(Iterable<T> range)
{
for (T x : range)
{
System.out.println(x);
}
}

显然,printB 涉及对 Object 的额外检查转换(请参阅第 16 行),这对我来说似乎相当愚蠢——反正一切不都是 Object 吗?

public static void printA(java.lang.Iterable);
Code:
0: aload_0
1: invokeinterface #18, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
6: astore_2
7: goto 24
10: aload_2
11: invokeinterface #24, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
16: astore_1
17: getstatic #30; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload_1
21: invokevirtual #36; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
24: aload_2
25: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
30: ifne 10
33: return

public static void printB(java.lang.Iterable);
Code:
0: aload_0
1: invokeinterface #18, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
6: astore_2
7: goto 27
10: aload_2
11: invokeinterface #24, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
16: checkcast #3; //class java/lang/Object
19: astore_1
20: getstatic #30; //Field java/lang/System.out:Ljava/io/PrintStream;
23: aload_1
24: invokevirtual #36; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
27: aload_2
28: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
33: ifne 10
36: return

最佳答案

在您的示例中,泛型类型恰好在签名的一个位置中使用。在这种情况下,类型 T与通配符相比,调用者没有任何优势。在您的示例中,该类型对于方法的实现者也没有优势。

我发现调用者更容易理解通配符版本,因为它明确表示“我根本不关心类型”

在您的示例中,checkcast确实是多余的。如果 T 则需要是有界的,就像在 T extends Number 中一样.然后检查 Number是必需的,因为局部变量 x将是 Number 类型,但是 Iterator.next()方法仍然返回 Object .似乎 Java 编译器不会费心优化类型转换。 JIT 可能会在运行时这样做。

更新:

如果通用类型在多个地方使用,就像 cletus 的回答中那样,您别无选择,只能使用通用类型 T ,否则编译器看不到参数类型/返回类型之间的联系(任何两个通配符对于编译器都是不同的)。

边界情况是签名只有一个位置的类型,但实现需要它是通用类型而不是通配符。想想 void swap(List<T> list, int a, int b)方法。它需要从列表中取出元素并将它们放回原处。IIRC,Effective Java 建议使用带有通配符的公共(public)方法,以及带有包含实际实现的类型的内部辅助方法。这样,用户获得了一个简单的 API,而实现者仍然具有类型安全性。

public void swap(List<?> list, int a, int b){
swapHelper(list, a, b);
}
private <T> void swapHelper(List<T> list, int a, int b){
...
}

关于java - 通配符与通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2753002/

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