2011-11-07 101 views
1

當我使用實現ArrayList的類並更改元素的泛型類型時,我發現了一些有趣的Java(或者至少是Netbeans)。我基本上創建了一個抽象類,它擴展了ArrayList和一些應該與String對象一起工作的子類(比如ArrayList<String>)。其中一件事我沒有嘗試做到這一點是這樣的:設置迭代器的Java泛型

public abstract class A extends ArrayList { 
    ... 
} 
@Override 
public abstract class B extends A { 
    public Iterator<String> iterator() { 
     return super.iterator(); 
    } 
} 

另一條是這樣的:

public abstract class A extends ArrayList { 
    ... 
} 
public abstract class B<String> extends A { 
    @Override 
    public Iterator<String> iterator() { 
     return super.iterator(); 
    } 
} 

第一個成功地覆蓋了iterator()方法分配字符串值給它。另一個以某種方式取消了類型轉換。有趣的是,當涉及到循環時,它們都不起作用。這收到類型Object而不是String

for (String s : B) { 
    ... 
} 

你知道爲什麼會發生這種情況,如何修復它而無需實現自己的迭代器?

+4

一般而言,您應[有利於構造而不是繼承](http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance)([Effective Java,Item 16](http://books.google.com/books?id= ka2VUBqHiWkC&PG = PA81&LPG = PA81&DQ =贊成+組合物+ +過度繼承+有效+ Java和源= BL&OTS = yYEfOms-O4&S IG = AzKrW2db1sgCyjTP_u1F2B8P_cY&HL = EN&EI = rQ64TubcAuH74QTF_qjkAw&SA = X&OI = book_result&CT =導致&resnum = 5&VED = 0CDkQ6AEwBA#V = onepage&Q&F =假))。你爲什麼首先擴展'ArrayList'? –

+0

你的意思是說,for循環s的類型是Object而不是String? – Tudor

回答

4

不知道你正在嘗試做的,但如果我理解正確的話,你想擴展ArrayList和有一個通用的字符串類型的類...也許你正在尋找爲此:

public abstract class A<T> extends ArrayList<T> { 
    ... 
} 
public abstract class B extends A<String> { 
    ... 
} 

然後在你的代碼,這樣的:

B myList = ...; 
for (String s : myList) { 
    ... 
} 

將工作得很好。雖然我認爲你可以想出更好的解決方案。你有關於你的問題的更多細節嗎?

+0

謝謝,那正是我想要做的。不過,你會推薦使用什麼呢? –

+0

@Aleksandar,我想我只是不明白_abstract_基類(在這個例子中是'A')。你可以擴展這個嗎? – Lucas

1

用的組合物,而不是繼承

public class A implements Iterable<String>{ 
     List<String> myList = new ArrayList<String>(); 
     //do operations on myList 
     public Iterator<String> iterator() { 
      return myList.iterator(); 
     } 
    } 
0

如果擴展泛型類,則應該關心泛型。我的意思是,你的聲明應該像

public abstract class A extends ArrayList<String> { 
    ... 
} 

,如果你想,如果你想你的類是一般性的使用字符串或

public abstract class <T> A extends ArrayList<T> { 
    ... 
} 

在這兩種情況下,您不必重寫iterator()方法:您可以從超類中調用它,它將返回「好」迭代器。您的聲明等同於

public abstract class A extends ArrayList<Object> { 
    ... 
} 

這就是「奇怪」行爲的原因。

順便問我可以問你爲什麼要延長ArrayList?這聽起來很奇怪。

+0

這是一個愚蠢的想法。我最終沒有這樣做。 –

0

OMG,這是可怕的:

public abstract class B<String> extends A { 
    @Override 
    public Iterator<String> iterator() { 
     return super.iterator(); 
    } 
} 

String是不是類String,相反,您聲明稱爲新的變量類型String(如T),其陰影類String

+0

感謝,解釋了很多。 –