什么是Java中的捕获转换,谁能给我举例?
我注意到JLS谈到5.1.10捕获转换 ,但我不明白它们是什么。
任何人都可以向我解释/举例吗?
捕获转换旨在制作通配符(在generics中),? 有用。
假设我们有以下类:
public interface Test { public void shout(T whatever); public T repeatPreviousShout(); }
我们的代码在某处,
public static void instantTest(Test> test) { System.out.println(test.repeatPreviousShout()); }
因为test
不是原始Test
,因为“ repeatPreviousShout()
”中的repeatPreviousShout()
返回一个?
,编译器知道有一个T
作为Test
的类型参数。 此T
用于某些未知的T
因此编译器会删除未知类型(对于通配符,它将替换为Object
)。因此, repeatPreviousShout()
将返回一个Object
。
但如果我们有,
public static void instantTest2(Test> test) { test.shout(test.repeatPreviousShout()); }
编译器会给我们一个错误,例如Test
(其中xxx
是一个数字,例如337
)。
这是因为编译器尝试对shout()
进行类型安全检查,但由于它收到了通配符,因此它不知道T
代表什么,因此它创建了一个名为capture of的占位符。
从这里(Java理论和实践:与generics一起疯狂,第1部分) ,它明确指出:
捕获转换允许编译器为捕获的通配符制作占位符类型名称,因此类型推断可以将其推断为该类型。
希望这对你有所帮助。
涉及通配符类型参数的参数化类型实际上是联合类型。 例如
List extends Number> = Union{ List | S <: Number }
在2例中,而不是使用List extends Number>
List extends Number>
,Java使用捕获的版本List
,其中S是刚创建的带有上限Number
类型变量。
(1) http://java.sun.com/docs/books/jls/third_edition/html/expressions.html
缩小表达式的类型。 如果表达式的类型是List extends Number>
List extends Number>
,我们确定对象的运行时类型实际上是某个具体类型S( S <: Number>
)的List
。 因此编译器使用List
来执行更准确的类型分析。
捕获转换分别应用于每个表达式; 这会导致一些愚蠢的结果:
void test1(List a){} void test2(List a, List 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 :< B
其中A
涉及通配符参数。 例如,
List extends Number> :< B <=> Union{ List | S <: Number} :< B <=> List :< B, for all S <: Number
因此,实际上,我们正在检查A
类型的捕获版本