2013-03-08 118 views
1

代碼問題與泛型

interface BaseIntr<T>{ 
     void saveSwiftMsg(Collection<String> headers) throws Exception; 
    } 

class Impl implements BaseIntr{ 
     public void saveSwiftMsg(Collection<String> headers) throws Exception { }  
    } 

EDITED版本的代碼:

interface BaseIntr<T>{ 
    T process(T t); 
    void saveSwiftMsg(Collection<String> headers)  throws Exception; 
    } 

    class Impl implements BaseIntr{ 
    public void saveSwiftMsg(Collection<String> headers) throws Exception { } 
    @Override 
    public Object process(Object t) {  return t; } 
    } 

工作環境

Java版本:1.7.0_04,供應商:甲骨文公司

默認區域:en_IN,平臺編碼:的Cp1252

操作系統名稱: 「Windows 7的」 版本: 「6.1」,拱: 「AMD64」,家人: 「窗口」

Java編譯器投以下例外。但是如果我從BaseIntr中刪除< T>,它工作正常。

javac gen\GenericsTest.java 
gen\GenericsTest.java:18: error: Impl is not abstract and does not override abstract  method saveSwiftMsg(Collection) in BaseIntr 
class Impl implements BaseIntr{ 
^ 
gen\GenericsTest.java:20: error: name clash: saveSwiftMsg(Collection<String>) in Impl and saveSwiftMsg(Collection<String>) in BaseIntr have the same erasure, yet neither overrides the other 
public void saveSwiftMsg(Collection<String> headers) throws Exception { 
       ^
2 errors 
+1

你爲什麼使界面通用?你不要在任何地方使用'T' ... – assylias 2013-03-08 12:25:30

+0

確保Collection類是相同的,以及方法名稱是相同的(一個字符可以用不同的語言編寫)。 編輯:這很奇怪,它不能缺少@Override? 此外,嘗試使用某些參數化「實現BaseIntr」,例如執行BaseIntr dkateros 2013-03-08 12:27:10

+0

@assylias,是否使用T是強制性的,儘管沒有使用,但它幾乎沒有任何意義。 – 2013-03-08 12:30:16

回答

2

如果您在不指定其類型參數的情況下使用泛型類型(implements BaseIntr),則使用原始類型。這些是由defined Java語言規範如下:

爲了促進與非通用舊代碼交互,能夠爲一種類型使用擦除(§4.6)的參數化類型的(§4.5)或擦除其元素類型爲參數化類型的數組類型(第10.1節)。這種類型被稱爲原始類型。

更準確地說,原始類型被定義爲是以下之一:

  • 其是通過取一個通用類型聲明的名稱不具有伴隨的類型參數列表形成的引用類型。

的類型構造函數(§8.8),實例方法(8.4節,第9.4節),或者非靜態字段(§8.3)原始類型的M C不是從它的超類或超接口繼承的是原始類型,它對應於在對應於C的通用聲明中刪除其類型的原始類型。

即,繼承的方法具有簽名

saveSwiftMsg(Collection headers) throws Exception 

要覆蓋,最重要的方法必須具有相同的簽名繼承一個。它不會導致編譯錯誤。

我強烈建議只使用原始類型用於其預期用途(與傳統代碼接口),並啓用(並修復)相應的編譯器警告。

對於這個問題,所以確實說明書:

使用原始類型被允許僅作爲讓步的遺留代碼兼容。強烈建議在將泛型引入Java編程語言之後編寫的代碼中使用原始類型。未來版本的Java編程語言可能會禁止使用原始類型。

爲確保始終標記可能違反打字規則的行爲,對原始類型成員的某些訪問將導致編譯時未經檢查的警告。用於訪問成員或原始類型的構造時編譯時未檢查警告的規則如下:

  • 在一個分配給一個字段:如果左手操作數的類型是原始類型,則如果擦除更改字段的類型,則會發生編譯時未檢查警告。

  • 在調用方法或構造方法時:如果要搜索的類或接口的類型(第15.12.1節)是原始類型,那麼如果擦除更改任何正式方法,則會發生編譯時未檢查警告方法或構造函數的參數類型。

你應該注意的是編譯器警告,並指定實現接口的類型參數。

1

你neeed在子類中指定也

class Impl implements BaseIntr<T>{ 
     public void saveSwiftMsg(Collection<String> headers) throws Exception { }  
    } 

其實你內斯指定type.That是好樣的

interface BaseIntr<String>{ 
     void saveSwiftMsg(Collection<String> headers) throws Exception; 
    } 

class Impl implements BaseIntr<String>{ 
      public void saveSwiftMsg(Collection<String> headers) throws Exception { }  
     } 
+0

實施原始列表是否違法? – 2013-03-08 12:27:15

3

你的接口參數化與類型T時你執行它,你必須指定它的類型是這樣的:

class Impl implements BaseIntr<String>{ 
} 

這就是如果你想實現它String。但是,您可以將參數委託給實現類:

class Impl<T> implements BaseIntr<T>{ 
} 

然後,您需要在實例化類時指定類型。

+0

在兒童中使用泛型不是強制性的,對吧?我可能不會在實施中使用泛型。 – 2013-03-08 12:33:18