2009-11-02 42 views
1

我想知道如何在java中運行時識別子類。在我的程序中,我調用了一個返回超類對象的方法。該對象可以是其任何一個子類的實例。我想知道該對象是運行時哪個子類的實例,以便我可以將其轉換爲該子類並訪問子類方法。任何人都可以幫助我嗎?在對象上在運行時識別子類

感謝

+0

謝謝..現在我知道該怎麼做了,Iam試圖改變設計以避免這種編碼 – daniel 2009-11-02 09:34:27

回答

4

調用getClass()的訪問類的對象,告訴您該對象的實際類型。然後,您可以將它與任何類的「.class」靜態成員進行比較。

if (obj.getClass().equals(Foo.class)) { ... } 

然而,很多人會說你的建議是壞設計。確保它是必要的,並考慮替代品。在實現像equals()這樣的方法時通常是必需的。

+2

我認爲instanceof是一種更好的方法,但是您得到我的投票指出這確實表明設計是錯誤的。 – Dustin 2009-11-02 06:51:40

+0

通過equals()比較Class對象沒有意義。這可以替換爲簡單的==。 – 2009-11-02 10:10:14

+0

考慮到問題陳述,我不同意instanceof是解決方案。他有興趣根據對象的確切類別採取行動,而instanceof並沒有完全捕捉到這種情況:只要參數與給定的類是分配兼容的,而不是僅僅是一個實例,情況就是如此。在某些情況下,這是等同的,但不是全部。 – 2009-11-02 17:43:16

0

您可以使用instanceof運算符來測試對象的類型,然後進行轉換。

1

使用instanceof運算符。像這樣

Superclass aSup = ...; 
if(aSup instanceof Subclass) { 
    Subclass aSub = (Subclass) aSup; 
    aSub.subclass_method(...); 
} 
7

您可以使用instanceof來檢查對象是否是特定類的實例。例如:

if (animal instanceof Cat) { 
    Cat cat = (Cat) animal; 
    cat.meow(); 
} else if (animal instanceof Dog) { 
    Dog dog = (Dog) animal; 
    dog.bark(); 
} 

但是,過度使用instanceof(或向下轉換,就此而言)通常被認爲是設計不佳的標誌。反而利用多態性更好。例如,在Animal中有一個(可能是抽象的)「speak」方法,然後每個子類都有不同的實現。上面的代碼將被用電話代替說話了:

animal.speak(); 
+0

+1,用於解釋使用'instanceof'是不良設計的一個症狀。 – Jesper 2009-11-02 10:22:11

1

注意,如果對象是一個類型分配給指定的 類的instanceof是真實的。以下(如上所述)將工作

if (o instanceof Cat.class) { 
    // .. 
} else if (o instanceof Dog.class) { 
    // .. 
} else { 
    throw IllegalArgumentException("Unexpected type"); 
} 

但是,如果你引入一個新的貓的子類,例如虎然後 第一個子句將被觸發,除非你更新了所有代碼 這樣做。

您可能想要搜索雙重調度 必須做到上述,當然不知道你的問題 試圖解決這個可能不適用。

1

您可以像上面提到的那樣使用'instanceof'操作符和直接的Class對象比較。

但是,如果你想修改代碼以避免明確的檢查,我看到兩條路走:


interface Handler<T> { 
    void handle(T object); 
} 

Map<Class<?>, Handler<?>> HANDLERS = /* init handlers mappings */; 

... 

public void process(Object obj) { 
    Handler<?> handler = HANDLERS.get(obj.getClass()); 
    if (handler == null) { 
     throw new IllegalStateException("bla-bla-bla, no handler is registered for class " + obj.getClass()); 
    } 
    handler.handle(obj); 
}