簡體   English   中英

Java Generics - 這個未經檢查的演員安全嗎?

[英]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);
}

你期望這種方法永遠不會失敗,對吧? 畢竟,你只是確保tT (因為你有一個Class<T> ),我們已經知道它 T因為write()只接受一個T 對? 錯誤! 您實際上並不檢查是否tT ,但潛在的一些任意亞型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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM