[英]Java Generics - is this unchecked cast safe?
我有(另一個)未經檢查的演員問題。 我90%確定它是安全的,但我想確定(我正在證明將@SupressWarnings
用於正在審查代碼的其他開發人員)
我們的框架已經建立了以下模式:
abstract class Writer<T> {
Class<T> valueType;
Writer(Class<T> valueType) {
this.valueType = valueType;
}
}
class Cat { }
class CatWriter extends Writer<Cat> {
CatWriter() {
super(Cat.class);
}
}
我也使用Writer
的子類來編寫一個使用泛型的類:
class Color {}
class Green extends Color {}
class Brown extends Color {}
我的作家類看起來像這樣:
abstract class Bird<C extends Color> {}
class Parrot extends Bird<Green>{}
class Ostrich extends Bird<Brown>{}
class BirdWriter<C extends Color> extends Writer<Bird<C>> {
BirdWriter(Bird<C> bird) {
super((Class<Bird<C>>)bird.getClass());
}
}
我可以在編寫器中使用原始類型但是會提供更多警告。 相反,我在Writer類中包含泛型。 除了構造函數之外,這到處都很好。 我不得不投的bird.getClass()
這是一類對象,它沒有一般簽名) 與通用簽署的Class對象。 這會在演員表上產生未經檢查的演員警告,但我相信將結果轉換為Class<Bird<C>>
是安全的,因為傳遞給參數的bird
肯定是Bird<C>
。
測試支持我的理論,但我想確保我的想法是正確的。 這段代碼有什么方法不安全嗎?
謝謝你的回答。 由於答案,我意識到我的結構存在缺陷,並對其進行了修改。
基本上Cat
使用一個簡單的Writer
,它知道它總是寫一個Cat
。 在我的例子中,我有一種可以由動態Writer編寫的“SmartAnimal”,因此我不必為每個Animal創建一個Writer
。
class SmartAnimal {}
class Dog extends SmartAnimal {}
class Horse extends SmartAnimal {}
class SuperHorse extends Horse {}
class DynamicWriter<A extends SmartAnimal> extends Writer<A> {
DynamicWriter(A smartAnimal) {
super((Class<A>)smartAnimal.getClass());
}
}
同樣,我有同樣的警告,但這似乎更安全。
這樣更好,安全嗎?
你並不完全正確。 正確的,安全的,但仍未經檢查的演員表是Class<? extends Bird<C>>
Class<? extends Bird<C>>
,因為您傳遞的鳥可以是一只貓頭鷹,它會返回一個Class<Owl>
,可以分配給一個Class<? extends Bird<C>>
Class<? extends Bird<C>>
。 彼得勞里是正確的,因為這是不受制約但安全的。
更新:
不,出於同樣的原因,它仍然不安全。 你仍然可以做一些像new DynamicWriter<Horse>(new SuperHorse());
這將執行從Class<SuperHorse>
到Class<Horse>
的未經檢查的演員表。 為了安全起見,你需要施放到一個Class<? extends A>
Class<? extends A>
。
由於ILMTitan 在他的回答中列出的原因,這肯定是不正確的。 但我會告訴你為什么它也可能不太安全。 想象一下,你有一個方法verifyType()
,它確保傳入的任何內容都是正確的類型:
public void write(T t) {
if (!verifyType(t)) explode();
//...do write
}
public boolean verifyType(T t) {
return valueType.isInstance(t);
}
你期望這種方法永遠不會失敗,對吧? 畢竟,你只是確保t
是T
(因為你有一個Class<T>
),我們已經知道它是 T
因為write()
只接受一個T
? 對? 錯誤! 您實際上並不檢查是否t
是T
,但潛在的一些任意亞型T
。
檢查如果你聲明一個Writer<Bird<Green>>
並用Parrot<Green>
實例化它會發生什么,這樣做是合法的 :
Writer<Bird<Green>> writer;
writer.write(new SomeOtherGreenBird());
再一次,你不會指望它會失敗。 但是,您的值類型僅適用於Parrot
,因此類型檢查將失敗。 這一切都取決於你在作家班上所做的事情,但要預先警告:你在這里踩着危險的水。 宣布一個Class<? extends T>
在你的作家中Class<? extends T>
會阻止你犯這樣的錯誤。
恕我直言,這是安全的。問題是getClass()在運行時返回對象的類,但是編譯器不理解getClass()的作用,也沒有類似的語法
Class<this> getClass();
可能是因為它是它何時被使用的唯一例子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.