Blankman
Blankman

Reputation: 267140

Converting this function to using generics

I have a function that I am trying to convert using generics, so far I have:

public static <T extends Enum<T> & SomeInterface> EnumSet<T> convertToES(long val) {
  EnumSet<T> es = EnumSet.noneOf(T.class);

  for(T t : values()) {
      if(t.getSomeProperty() > 0)
        es.add(t);
  }


  return es;
}

Where SomeInterface has a single property getSomeProperty.

T.class isn't working, and also values() doesn't seem to work.

Previously I had:

public static EnumSet<SomeType> convertToES(long val) {
        EnumSet<SomeType> es = EnumSet.noneOf(SomeType.class);

        for (SomeType p : values()) {
            if (p.getSomeThing())) > 0) {
                es.add(p);
            }
        }

        return es;
    }

Is there a way to make this work, or it is not possible?

Upvotes: 1

Views: 111

Answers (3)

PaulMurrayCbr
PaulMurrayCbr

Reputation: 1260

The method does not know which enumset you want - it can't know. I'd suggest just passing it in:

public static <T extends Enum<T> & SomeInterface> //
        EnumSet<T> convertToES(Class<T> tClass, long val) {
    EnumSet<T> set = EnumSet.noneOf(tClass);
    for (T t : EnumSet.allOf(tClass)) {
        if (t.getSomeProperty() == val) {
            set.add(t);
        }
    }
    return set;
}

Call it like so:

EnumSet<Foo> x = convertToES(Foo.class, 3);

Or even

for(Foo suitableFoo: convertToES(Foo.class, 5)) {
    print(suitableFoo + " has a property of 5!");
}

Upvotes: 0

Knut Forkalsrud
Knut Forkalsrud

Reputation: 1174

T.class isn't working because T is not a class. You probably need introspection. I suggest something along the lines of:

public static <T extends Enum<T> & SomeInterface> EnumSet<T> convertToES(Class<T> clazz, long val) {

    EnumSet<T> es = EnumSet.noneOf(clazz);

    for(T t : clazz.getEnumConstants()) {
        if(t.getSomeProperty() > 0)
          es.add(t);
    }
    return es;
  }

Upvotes: 0

StriplingWarrior
StriplingWarrior

Reputation: 156624

This is because Java implements generics via erasure so T doesn't exist at runtime. Generics in Java is just a language tool to help you avoid making too many mistakes that could be caught at compile time.

The solution is to require the person calling the method to give you the class itself as a real argument:

public static <T extends Enum<T> & SomeInterface> EnumSet<T> convertToES(
    long val,
    Class<T> tClass) 
{
    EnumSet<T> es = EnumSet.noneOf(tClass);

As far as values() is concerned, that method exists on the enum class itself, so if you've moved the code out of that class, you'll need to get the values another way:

    for(T t : tClass.getEnumConstants()) {
        ....

Upvotes: 3

Related Questions