2013-02-15 78 views
0

我正在寫一個通用編碼器/解碼器,並遇到擴展通用的問題。想法 是我想有一個抽象的Encodeable類,它有一個「虛擬」靜態方法解碼,它需要一個Byte []並構造對象,類似於Serializable。 (我知道這實際上不能用java來完成。)每個擴展Encodeable的類都會覆蓋 編碼/解碼方法。然後我想通常使用這些可編碼的子類。下面是一個試圖表明我的意思:java通用擴展類型錯誤

public class Encodeable{ 

    // I'd like to write 
    // static abstract Encodeable decode(Byte[]); 
    // similar to 
    // virtual Encodeable decode(Byte[]) = 0; 
    // in C++, but that seems to be illegal in java 

    static Encodeable decode(Byte[] buf){return null}; 

} 

public class EncodeableFoo extends Encodeable{ 

     static EncodeableFoo decode(Byte[] buf){ 
      // do actual decoding logic here 
     } 

} 

public class Bar<T extends Encodeable>{ 

    public void messageReceived(MessageEvent e){ 
     Byte[] buf = e.getMessage(); 
     T messageObj = T.decode(buf); 
     // do something with T 
    } 

} 

由於是,我得到一個錯誤消息像

error: incompatible types 
    T messageObj = T.decode(objBuf); 
         ^
    required: T 
    found: Encodeable 
    where T is a type-variable: 
    T extends Encodeable declared in class EdgeClientHandler 

在編譯時。但如果我將解碼線更改爲

T messageObj = (T) T.decode(objBuf); 

它工作得很好。有人能向我解釋這個黑魔法嗎?或者,更重要的是,給我一個更好的方式來編寫我的通用Bar類,以便它知道T有一個靜態方法解碼(和一個非靜態方法編碼)?

回答

6

First, static methods in Java cannot be abstract.

其次,你需要聲明的方法,如果您希望編譯器知道您返回T是通用的,不只是一個Encodeable。我建議在這裏完全遠離static。其基本思路:

public interface Decoder<T> { 
    T decode(Byte[] buf); 
} 

public class FooDecoder implements Decoder<Foo> { 
    Foo decode(Byte[] buf){ 
     // do actual decoding logic here 
    } 
} 

public class Bar<T extends Encodeable> { 

    private Decoder<T> decoder; // you'll have to figure out where to get this 

    public void messageReceived(MessageEvent e){ 
     Byte[] buf = e.getMessage(); 
     T messageObj = decoder.decode(buf); 
     // do something with T 
    } 
} 

原始設置似乎可編碼的混合類型和事情,懂得這種類型從byte[]解碼,所以我改名爲撥弄了一下。


方的問題:爲什麼Byte[] s,而不是byte[] S'

+2

哈哈 - 得到了相同的結論;-) – assylias 2013-02-15 17:22:06

+1

是的,非常準確地 - 我想你的代碼實際上更接近正確的 – 2013-02-15 17:26:25

3

您的設計看起來有點凌亂。我不會用一個靜態方法,做這樣的事情,而不是:

public interface Decoder<T extends Encodable> { 
    T decode(Byte[] buf); 
} 

public class Bar<T extends Encodable> { 
    private final Decoder<T> decoder; 

    public Bar(Decoder<T> decoder) { 
     this.decoder = decoder; 
    } 

    public void messageReceived(MessageEvent e) { 
     Byte[] buf = e.getMessage(); 
     T messageObj = decoder.decode(buf); 
     // do something with T 
    } 
}