Dhan
Dhan

Reputation: 91

Problem when trying to use generics

I have a class

public abstract class AbstractE<T, E extends Enum<E> & Flags>
{
     public interface Flags{} /*marker interface*/
     //... 
     //other code
}

and an interface

public interface IXYZAdapter
{
   public <E extends Enum<E> & Flags> Set<E> getFlags();
}

Where Flags is an interface defined in AbstractE itself.

M extends AbstractE thus:

public class M extends AbstractE<Long, M.EF> implements IXYZAdapter
{
    public enum EF implements AbstractE.Flags{flag1, flag2}
    @Override /*from IXYZAdapter*/
    public Set<M.EF> getFlags()
    {return EnumSet.allOf(EF.class);}
    
}

Now, from the main code, I try to get a handle on the interface IXYZAdapter and invoke the getFlags method

IXYZAdapter adapter = (IXYZAdapter)m; //where m is an instance of AbstractE
Set s = adapter.getFlags();

I get the following compile time error in the main program last line (Set s = adapter.getFlags();)

invalid inferred types for E; inferred type does not conform to declared bound(s)

inferred: AbstractE.Flags

bound(s): java.lang.Enum<AbstractE.Flags>,AbstractE.Flags

What am I doing wrong? I am using Java 6

Edited to specify the error location

Upvotes: 3

Views: 3712

Answers (2)

Thomas
Thomas

Reputation: 88707

Try this:

public interface IXYZAdapter <E extends Enum<E> & AbstractE.Flags>
{
   public Set<E> getFlags();
}

And

public class M extends AbstractE<Long, M.EF> implements IXYZAdapter<M.EF> 
{
}

Or

Set<M.EF> s = adapter.getFlags();

The problem is that with Set s = adapter.getFlags(); The system doesn't know which type to infer for E in IXYZAdapter and thus the E in AbstractE doesn't match.

Edit:

Another option might be:

interface IXYZAdapter <E extends Enum<E> & AbstractE.Flags>
{
  public Set<? extends E> getFlags();
}

class M extends AbstractE<Long, M.EF> implements IXYZAdapter<M.EF>
{
  public enum EF implements AbstractE.Flags{flag1, flag2}
  public Set<? extends M.EF> getFlags()
  {return EnumSet.allOf(EF.class);}

}

And the call: Set<? extends AbstractE.Flags> s = adapter.getFlags();

This would allow you to get a set of flags without casting and force the flags to be declared as enum.

Upvotes: 2

davogotland
davogotland

Reputation: 2777

using the first solution thomas provided, the main method can be written like this to become warning free without actually having to know about the enum type:

public static void main(String[] args) {
    M m = new M();
    IXYZAdapter<?> adapter = (IXYZAdapter<?>)m;
    Set<?> flags = adapter.getFlags();
    Iterator<?> it = flags.iterator();

    while(it.hasNext()) {
        System.out.println(it.next());
    }
}

Upvotes: 0

Related Questions