Forum Stats

  • 3,852,841 Users
  • 2,264,141 Discussions
  • 7,905,157 Comments

Discussions

How to do Collections.EMPTY_SET in Generics?

843793
843793 Member Posts: 41,732 Green Ribbon
edited Nov 1, 2002 1:02PM in Generics
In non-Generic code, I sometimes use Collections.EMPTY_SET:
public class Test
{
    private Set setWhichCanBeNull;

    public Test( Set setWhichCanBeNull )
    {
        this.setWhichCanBeNull = setWhichCanBeNull;
    }

    public Set getSet()
    {
        return ( setWhichCanBeNull == null )
            ? Collections.EMPTY_SET
            : setWhichCanBeNull;
    }
}
If I write this using Generics, Collections.EMPTY_SET does not work, since it does not know what type I am interested in:
public class Test<E>
{
    private Set<E> setWhichCanBeNull;

    public Test( Set<E> setWhichCanBeNull )
    {
        this.setWhichCanBeNull = setWhichCanBeNull;
    }

    public Set<E> getSet()
    {
        return ( setWhichCanBeNull == null )
            ? Collections.EMPTY_SET
            : setWhichCanBeNull;
    }
}
Is there any way to specify something like this:
Collections<E>.EMPTY_SET
or am I stuck with having to write:
    public Set<E> getSet()
    {
        return ( setWhichCanBeNull == null )
            ? new HashSet<E>()
            : setWhichCanBeNull;
    }
Thanks.

Geoff

Comments

  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I wish I knew. I sent this same question to the JSR 14 expert group during the public review process. Apparently the question was either too trivial or too much of a stumper to warrant a response.

    Another question I asked, which seems even more problematic, was the question of how addAll() will work. In the public review collections API, it was declared as:
    interface Collection<E> {
      void addAll(Collection<E> stuff);
    }
    That prevents the following from working:
       List<String> x;
       List<Object> y;
       ...
       y.addAll(x);
    Yikes!! That alone would be reason to vote down the JSR in my mind. Really, there should be a way to declare addAll() something like this:
    interface Collection<E> {
      void addAll(Collection<T extends E> stuff);
    }
    Does anyone know if this problem was/will be fixed in the final draft for JSR 14?
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    This won't work?
    interface Collection<E> {
      <T extends E> void addAll(Collection<T> stuff);
    }
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    It works with the actual prototype compiler (v 1.2).
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    The short answer is: you can't do that. However, you
    can make a method that returns the empty set.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    schapel wrote:
    This won't work?

    interface Collection<E> {
    <T extends E> void addAll(Collection<T> stuff);
    }
    joerg.wassmer wrote:
    It works with the actual prototype compiler (v 1.2).
    Great! I just downloaded the new prototype, and it does indeed work. This was broken in the version I downloaded about 8 months ago, and I'm very glad to see that it was fixed.

    So here's a stumper. Suppose I have the following:
    public interface Event { }
    
    public class EventSuper implements Event { }
    
    public class EventSub extends EventSuper { }
    
    public class EventListener<E extends Event>
        {
        public void handleEvent(E event)
            { System.out.println("got event: " + event); }
        }
    
    public class EventBroadcaster<E extends Event>
        {
        public void addListener(EventListener<E> listener)
            { listeners.add(listener); }
            
        public void removeListener(EventListener<E> listener)
            { listeners.remove(listener); }
        
        public void broadcast(E event)
            {
            for(Iterator<EventListener<E>> i = listeners.iterator(); i.hasNext(); )
                i.next().handleEvent(event);
            }
        
        private List<EventListener<E>> listeners = new LinkedList<EventListener<E>>();
        }
    Really, I ought to be able to do this:
        EventBroadcaster<EventSub> b = new EventBroadcaster<EventSub>();
        EventListener<EventSuper> l = new EventListener<EventSuper>();
        b.addListener(l);
        b.broadcast(new EventSub());
    How do I finesse the EventBroadcaster and EventListener to allow that?
This discussion has been closed.