【问题标题】:What is a capture conversion in Java and can anyone give me examples?什么是 Java 中的捕获转换,谁能给我例子?
【发布时间】:2010-12-13 17:38:32
【问题描述】:

我注意到 JLS 谈到 5.1.10 Capture Conversion,但我不明白它们是什么。

谁能给我解释/举例?

【问题讨论】:

  • 除了下面的讨论之外没有其他例子?
  • 没错,他们提供了一个示例,但从中我无法理解捕获转换是什么。你明白这个例子了吗?如果是这样,您能否向我解释一下它们是什么。谢谢。
  • 通配符捕获和辅助方法docs.oracle.com/javase/tutorial/java/generics/capture.html 基本上:给定一个List<?> i,辅助方法将捕获的通配符转换为辅助方法中的已知类型<T>,因此现在您可以调用List<T> l 的方法 set() 需要已知类型。

标签: java capture jls


【解决方案1】:

捕获转换旨在使通配符(在泛型中)? 有用。

假设我们有以下类:

public interface Test<T> {
    public void shout(T whatever);
    public T repeatPreviousShout();

}

在我们的代码中某处,

public static void instantTest(Test<?> test) {
    System.out.println(test.repeatPreviousShout());
}

因为test 不是原始的Test,并且由于“后见之明”中的repeatPreviousShout() 返回一个?,所以编译器知道有一个T 作为Test 的类型参数。 这个T 用于一些未知的T,因此编译器会删除未知类型(对于通配符,它​​会替换为Object)。因此repeatPreviousShout() 返回一个Object

如果我们有,

public static void instantTest2(Test<?> test) {
    test.shout(test.repeatPreviousShout());
}

编译器会给我们一个类似Test&lt;capture#xxx of ?&gt; cannot be applied 的错误(其中xxx 是一个数字,例如337)。

这是因为编译器尝试对 shout() 进行类型安全检查,但由于它收到一个通配符,它​​不知道 T 代表什么,因此它创建了一个名为 capture of 的占位符em>。

来自here (Java theory and practice: Going wild with generics, Part 1),明确指出:

捕获转换允许 编译器制造占位符 为捕获的通配符键入名称, 这样类型推断就可以推断出 是那种人。

希望对你有所帮助。

【讨论】:

【解决方案2】:

涉及通配符类型参数的参数化类型实际上是联合类型。例如

List<? extends Number> = Union{ List<S> | S <: Number }

在 2 种情况下,Java 不使用 List&lt;? extends Number&gt;,而是使用捕获的版本 List&lt;S&gt;,其中 S 是刚刚创建的类型变量,上限为 Number

(1)http://java.sun.com/docs/books/jls/third_edition/html/expressions.html

缩小表达式的类型。如果表达式的类型是List&lt;? extends Number&gt;,我们肯定知道对象的运行时类型实际上是某个具体类型S(S &lt;: Number&gt;)的List&lt;S&gt;。因此编译器改用List&lt;S&gt; 来执行更准确的类型分析。

捕获转换分别应用于每个表达式;这会导致一些愚蠢的结果:

<T> void test1(List<T> a){}
<T> void test2(List<T> a, List<T> b){}

List<?> x = ...;
test1(x);    // ok
test2(x, x); // error

(2)http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10.2

A :&lt; B 子类型检查中,A 涉及通配符参数。例如,

List<? extends Number>  :< B
<=>
Union{ List<S> | S <: Number}  :< B
<=>
List<S> :< B, for all S <: Number

所以实际上,我们正在检查捕获的 A 类型的版本

【讨论】:

    猜你喜欢
    • 2013-02-04
    • 1970-01-01
    • 2020-09-19
    • 2013-06-06
    • 2022-07-06
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    相关资源
    最近更新 更多