使用泛型与实现相同接口的枚举类的集合

Xae*_*ess 6 java generics enums guava

我试图通过使用Guava 迭代es 列表来对几个实现相同接口的枚举类进行反向查找:FieldClassMaps.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;
    }
  }
Run Code Online (Sandbox Code Playgroud)

我不想在所有枚举类中重复相同的代码(用于制作索引和执行查找),因此我使用Fields包含Fields.valueOfSearchName方法的辅助静态类:

  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);
  }
Run Code Online (Sandbox Code Playgroud)

不幸的是,Eclipse显示错误:

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>
Run Code Online (Sandbox Code Playgroud)

问题是Class<? extends Enum<?>> clazz在for-each循环(不匹配字段),但我不知道如何处理这种情况下(很明显,我不能添加& Fieldclazz).

Xae*_*ess 3

受到Tom Hawtin 答案的Class启发,我创建了包含es的包装类,但仅限于那些带有签名的包装类<E extends Enum<E> & Field>

public final static class FieldEnumWrapper<E extends Enum<E> & Field> {
  private final Class<E> clazz;
  private final ImmutableMap<String, E> index;

  public static <E extends Enum<E> & Field> 
      FieldEnumWrapper<E> of(final Class<E> clazz) {
    return new FieldEnumWrapper<E>(clazz);
  }

  private FieldEnumWrapper(final Class<E> clazz) {
    this.clazz = clazz;
    this.index = Maps.uniqueIndex(
        EnumSet.allOf(clazz), new Function<E, String>() {
          @Override
          public String apply(final E input) {
            return input.searchName();
          }
        });
  }

  public Class<E> clazz() {
    return clazz;
  }

  public Field valueOfSearchName(final String searchName) {
    return index.get(searchName);
  }
}
Run Code Online (Sandbox Code Playgroud)

现在:

for (final FieldEnumWrapper<?> fieldEnum : ImmutableList.of(
    FieldEnumWrapper.of(EntityField.class),
    FieldEnumWrapper.of(AddressField.class),
    FieldEnumWrapper.of(PersonFunctionType.class))) {
  valueOfSearchName = fieldEnum.valueOfSearchName("POD_I_OS_PARTNER");
  // ...
Run Code Online (Sandbox Code Playgroud)

是类型安全的并且不恰当地使用 的FieldEnumWrapper静态工厂:

FieldEnumWrapper.of(NotEnumAndFieldClass.class)
Run Code Online (Sandbox Code Playgroud)

产生编译错误。

此外,valueOfSearchName现在是FieldEnumWrapper帮助类更有意义的方法。