Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using generics with collection of enum classes implementing same interface

I am trying to do reverse lookup on few enum classes implementing same Field interface by iterating through list of Classes using Guava's Maps.uniqueIndex:

  Field valueOfSearchName = null;
  for (final Class<? extends Enum<?>> clazz : ImmutableList.of(
      EntityField.class,
      AddressField.class,
      PersonFunctionType.class)) {
    valueOfSearchName = Fields.valueOfSearchName(clazz, term.field()); // error
    if (valueOfSearchName != null) {
      // do something...
      break;
    }
  }

I don't want to repeat same code (for making index and doing lookup) in all enum classes, so I use helper static class Fields containing Fields.valueOfSearchName method:

  public static <E extends Enum<E> & Field> Field valueOfSearchName(
      final Class<E> clazz, final String searchName) {
    // TODO: cache the index
    final ImmutableMap<String, E> index = Maps.uniqueIndex(
        EnumSet.allOf(clazz), GET_SEARCH_NAME_FUNCTION);
    return index.get(searchName);
  }

Unfortunately, Eclipse shows an error:

Bound mismatch: 
The generic method valueOfSearchName(Class<E>, String) of type Fields is not 
applicable for the arguments (Class<capture#1-of ? extends Enum<?>>, String).
The inferred type capture#1-of ? extends Enum<?> is not a valid substitute
for the bounded parameter <E extends Enum<E> & Field>

The problem is Class<? extends Enum<?>> clazz in for-each loop (not matching Field), but I don't know how to deal with this case (obviously I cannot add & Field to clazz).

like image 268
Xaerxess Avatar asked Dec 28 '11 15:12

Xaerxess


People also ask

Can enum implements interface?

Yes, Enum implements an interface in Java, it can be useful when we need to implement some business logic that is tightly coupled with a discriminatory property of a given object or class.

Can enum inherit interface?

Java Enum and Interface As we have learned, we cannot inherit enum classes in Java. However, enum classes can implement interfaces.

Can enums be generic?

However, it is possible to use enums in generics. The MSDN article for Enum gives the following type definition for the class Enum . This definition can be used to get enum s working as generic types by constraining the generic type to those of Enum .

Can you define multiple enums inside same class?

java file may have only one public class. You can therefore declare only one public enum in a . java file. You may declare any number of package-private enums.


1 Answers

Consider Class<? extends List<?>. Class<? extends List<?> has two wildcards whereas <E extends List<E>> Class<E> only has generic parameter. The former will admit Class<ArrayList<String>>. So without doing something extra special for enums, the types are not compatible.

How to fix? An extra layer of indirection!

public final class MetaEnum<E extends Enum<E>> {
    private final E clazz;
    public static <E extends Enum<E>> MetaEnum<E> of(E clazz) {
        return clazz;
    }
    private MetaEnum(E clazz) {
        this.clazz = clazz;
    }
    public E clazz() {
        return clazz;
    }
    // ...
}

for (final MetaEnum<?> meta : ImmutableList.of(
    MetaEnum.of(EntityField       .class),
    MetaEnum.of(AddressField      .class),
    MetaEnum.of(PersonFunctionType.class)
)) {
    Field valueOfSearchName = Fields.valueOfSearchName(
        meta.clazz(), term.field()
    );
    ...

(Usual Stack Overflow dislaimer: Not so much as attempted to compile.)

like image 170
Tom Hawtin - tackline Avatar answered Oct 23 '22 03:10

Tom Hawtin - tackline