2009-03-02 5 views
51

Учитывая следующий код, как я могу перебирать объект типа ProfileCollection?Как реализовать интерфейс Iterable?

public class ProfileCollection implements Iterable {  
    private ArrayList<Profile> m_Profiles; 

    public Iterator<Profile> iterator() {   
     Iterator<Profile> iprof = m_Profiles.iterator(); 
     return iprof; 
    } 

    ... 

    public Profile GetActiveProfile() { 
     return (Profile)m_Profiles.get(m_ActiveProfile); 
    } 
} 

public static void main(String[] args) { 
    m_PC = new ProfileCollection("profiles.xml"); 

    // properly outputs a profile: 
    System.out.println(m_PC.GetActiveProfile()); 

    // not actually outputting any profiles: 
    for(Iterator i = m_PC.iterator();i.hasNext();) { 
     System.out.println(i.next()); 
    } 

    // how I actually want this to work, but won't even compile: 
    for(Profile prof: m_PC) { 
     System.out.println(prof); 
    } 
} 
+0

эта статья может помочь вам: http://www.yegor256.com/2015/04/30/iterating-adapter.html – yegor256

ответ

58

Iterable - это общий интерфейс. Проблема, с которой вы могли столкнуться (вы на самом деле не сказали, какая у вас проблема, если таковая имеется) заключается в том, что если вы используете общий интерфейс/класс без указания аргументов типа, вы можете стереть типы несвязанных общих типов внутри класса. Пример этого - Non-generic reference to generic class results in non-generic return types.

Так что, по крайней мере, изменить его на:

public class ProfileCollection implements Iterable<Profile> { 
    private ArrayList<Profile> m_Profiles; 

    public Iterator<Profile> iterator() {   
     Iterator<Profile> iprof = m_Profiles.iterator(); 
     return iprof; 
    } 

    ... 

    public Profile GetActiveProfile() { 
     return (Profile)m_Profiles.get(m_ActiveProfile); 
    } 
} 

и это должно работать:

for (Profile profile : m_PC) { 
    // do stuff 
} 

Без типа аргумента Iterable, итератор может быть сведена к тому типу объекта так только это будет работать:

for (Object profile : m_PC) { 
    // do stuff 
} 

Это довольно неясный угловой случай Java-дженериков.

Если нет, предоставьте дополнительную информацию о том, что происходит.

+5

Просто предупреждение для вашего подхода; если вы просто пересылаете итератор из ArrayList, вы также перенаправляете на возможность удаления элементов. Если вы этого не хотите, вам придется обернуть итератор или обернуть ArrayList как сборку только для чтения. –

+0

Cletus, спасибо, ваше решение работает отлично. Проблема, с которой я столкнулась, была на самом деле именно тем, что вы описали. Тип возврата был Object instaead of Profile, извините. Эй, Джейсон, спасибо за комментарий. Как обернуть итератор? – Dewayne

+4

Я думаю, он имеет в виду: Collections.unmodifiableList (m_profiles) .iterator(). Это остановит вызывающего абонента, изменяющего arraylist – cletus

4

Во-первых:

public class ProfileCollection implements Iterable<Profile> { 

Второе:

return m_Profiles.get(m_ActiveProfile); 
+0

Что случилось с первой строкой? вы можете редактировать в объяснении? его очень непонятно, что не так. – Chii

+4

ах, наконец, увидел это, его генералитет. но выше все еще выполняется - просто вложите в то, что проблема, и что такое исправление, и это будет лучший ответ. – Chii

Смежные вопросы