[英]Is this cast in my generic method safe?
我的項目中的代碼如下所示:
public interface Bar<T extends Foo<?>> {
//...
}
public class MyFoo implements Foo<String> {
private List<Bar<Foo<String>> barFoo = ...
public <U extends Foo<String>> boolean addBar(Bar<? extends U> b) {
barFoo.add((Bar<Foo<String>>) b); //safe cast?
}
}
Eclipse為addBar
中的addBar
提供了警告,表明addBar
是不安全的。 但是,我是否正確假設投射不會因為我對類型參數施加的限制而拋出,因此投射確實安全?
不一般。
假設Bar
有一個方法void get(T value)
,並且有兩個實現Foo<String>
, MyFoo
和YourFoo
。 現在假設調用者在類型為Bar<MyFoo>
的值上調用addBar
。 這有效:當U
= Foo<String>
,我們有Bar<MyFoo>
是Bar<? extends U>
的子類型Bar<? extends U>
Bar<? extends U>
。 現在我們將該值轉換為Bar<Foo<String>>
。
現在如果Bar
沒有接受T
作為參數的方法,那就沒問題了。 但是假設它有一個方法void process(T value)
。 我們調用的實現有T
= MyFoo
,所以它只有一個process(MyFoo value)
方法。 但是,一旦我們將它轉換為Bar<Foo<String>>
,我們可能會用YourFoo
調用它。 這是非法的。
在黑暗中刺傷,但我懷疑你真正想做的是將barFoo
聲明為List<? extends Bar<? extends Foo<String>>
List<? extends Bar<? extends Foo<String>>
List<? extends Bar<? extends Foo<String>>
。
這不是一個安全的演員。 Eclipse是對的。
想象一下,你有一個擴展Foo
的類MyFoo
,你傳入了一個Bar<MyFoo<String>>
現在,當只編譯了myMethod(MyFoo x)
簽名時, Bar
一些方法帶有myMethod(Foo x)
簽名,因此方法查找會失敗的。
鑄造是不安全的,因為雖然U
延伸Foo<String>
,它不是 (必須的),該案Bar<U>
延伸Bar<Foo<String>>
。 事實上, Bar<U>
只會在它們是相同的東西時擴展Bar<Foo<String>>
,即當U
是Foo<String>
。
直覺上,似乎(例如) List<String>
應該是List<Object>
的子類型,但這不是泛型的工作方式。 List<String>
是List<? extends Object>
的子類型List<? extends Object>
List<? extends Object>
,但它不是 List<Object>
的子類型。 (考慮像Comparable<T>
這樣的例子可能更有意義: Comparable<String>
意味着“可以與任何String
進行比較,而Comparable<Object>
意味着”可以與任何Object
進行比較。)應該清楚可Comparable<String>
不應該是Comparable<Object>
的子類型。)
[...]演員不會扔[...]因此演員確實安全嗎?
我認為你誤解了警告的性質。 Eclipse警告你, 即使應該這樣做,這個演員也不會拋出,這實際上是為什么它不安全。 例如,這段代碼:
final Object o = Integer.valueOf(7);
final String s = (String) o;
是非常安全的,因為演員會拋出異常。 但是這段代碼:
final List<?> wildcardList = new ArrayList<Integer>(Integer.valueOf(7));
final List<String> stringList = (List<String>) wildcardList;
是不安全的 ,因為運行時無法檢查stringList
(由於擦除),因此它不會拋出異常,即使它是錯誤的: stringList
現在是一個List<String>
其第一個元素是Integer
類型。 (接下來會發生什么事情,當您嘗試對該元素執行某些操作時,您可以獲得自發的ClassCastException
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.