tags:

views:

3416

answers:

2

Given the following code, how can I iterate over an object of type ProfileCollection?

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);
     }
}
+10  A: 

Iterable is a generic interface. Once problem yo umight be having (you haven't actually said what problem you're having, if any) is that if you use a generic interface/class without specifying the type argument(s) you can erase the types of unrelated generic types within the class. An example of this is in Non-generic reference to generic class results in non-generic return types.

So I would at least change it to:

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);
    }
}

and this should work:

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

Without the type argument on Iterable, the iterator may be reduced to being type Object so only this will work:

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

This is a pretty obscure corner case of Java generics.

If not, please provide some more info about what's going on.

cletus
Just a warning to your approach; if you just forward the iterator from ArrayList, you also forward on the ability to remove items. If you don't want that, you'd have to wrap the iterator, or wrap the ArrayList as a readonly collection.
Jason S
Cletus, thank you your solution works perfectly. The problem I was having was actually exactly what you described. The return type was Object instaead of Profile, sorry. Hey Jason, thanks for the comment. How do I wrap the iterator?
Dewayne
I think he's referring to: Collections.unmodifiableList(m_profiles).iterator(). This will stop the caller modifying the arraylist
cletus
+2  A: 

First off:

public class ProfileCollection implements Iterable<Profile> {

Second:

return m_Profiles.get(m_ActiveProfile);
TofuBeer
what is wrong with the first line? can you edit in an explanation? its very unclear what is wrong.
Chii
ahh, finally saw it, its the generification. but the above still holds - just put in what the problem was, and what the fix was, and it would be a better answer.
Chii