Java 泛型不可能赋值?
Java generics impossible assignment?
每次我 认为 我更好地理解泛型(并且无需编译就可以回答),我得到一个这个理论被打破的例子。这是一个非常简单的例子:
static void consumer(List<? super List<String>> param) {
System.out.println(param);
}
还有两次调用:
public static void main(String[] args) {
List<String> list = List.of("123");
consumer(list);
consumer(List.of("123"));
}
对我来说,none 次调用应该可以编译。 String
不是 List
的超类型。尽管如此,第二个编译。但是让我们假设发生这种情况是因为编译器可以在这里推断出 some 类型。当然这样的类型是不存在的,它会在运行时失败,对吧?正确的?没有。它只是工作。因此,有人可以给我的生活带来一些理智吗?
啊该死!
javac --debug=verboseResolution=all Sandbox.java
表明consumer(List.of("123"))
被编译为:
instantiated signature: (Object)List<Object>
target-type: List<? super List<String>>
如果你想要一个更“功能”的解释,你必须考虑什么是param
。
通过应用 PECS,请注意因此 List
是 List<String>
的消费者。
- 兼容的消费者是那些可以消费
List<String>
或其任何父类型的消费者;
- 应用于
List
时,表示可以调用add()
的列表,父类型为List<String>
。因此 List<Object>
是兼容的。
这就是为什么 consumer()
可以用 List<Object>
而不是 List<String>
调用的原因(String
不是 List<String>
的超类型)。
由于List.of(…)
在声明时总能匹配List<Object>
,它接受第二次调用。
请注意,从 consumer()
方法内部,您将永远无法从 param
中检索 List<String>
(即,将其用作生产者)。您只能将新的添加到其中(即,将其用作消费者)——实际上,您可以将 List<String>
添加到 List<Object>
中(尽管在这种特殊情况下,List.of()
会产生一个不可变列表,因此它会在运行时失败)。
每次我 认为 我更好地理解泛型(并且无需编译就可以回答),我得到一个这个理论被打破的例子。这是一个非常简单的例子:
static void consumer(List<? super List<String>> param) {
System.out.println(param);
}
还有两次调用:
public static void main(String[] args) {
List<String> list = List.of("123");
consumer(list);
consumer(List.of("123"));
}
对我来说,none 次调用应该可以编译。 String
不是 List
的超类型。尽管如此,第二个编译。但是让我们假设发生这种情况是因为编译器可以在这里推断出 some 类型。当然这样的类型是不存在的,它会在运行时失败,对吧?正确的?没有。它只是工作。因此,有人可以给我的生活带来一些理智吗?
啊该死!
javac --debug=verboseResolution=all Sandbox.java
表明consumer(List.of("123"))
被编译为:
instantiated signature: (Object)List<Object>
target-type: List<? super List<String>>
如果你想要一个更“功能”的解释,你必须考虑什么是param
。
通过应用 PECS,请注意因此 List
是 List<String>
的消费者。
- 兼容的消费者是那些可以消费
List<String>
或其任何父类型的消费者; - 应用于
List
时,表示可以调用add()
的列表,父类型为List<String>
。因此List<Object>
是兼容的。
这就是为什么 consumer()
可以用 List<Object>
而不是 List<String>
调用的原因(String
不是 List<String>
的超类型)。
由于List.of(…)
在声明时总能匹配List<Object>
,它接受第二次调用。
请注意,从 consumer()
方法内部,您将永远无法从 param
中检索 List<String>
(即,将其用作生产者)。您只能将新的添加到其中(即,将其用作消费者)——实际上,您可以将 List<String>
添加到 List<Object>
中(尽管在这种特殊情况下,List.of()
会产生一个不可变列表,因此它会在运行时失败)。