首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有多个边界的Enum和泛型“期望的接口”

具有多个边界的Enum和泛型“期望的接口”
EN

Stack Overflow用户
提问于 2013-05-17 16:26:41
回答 2查看 640关注 0票数 0

我希望能够将枚举映射到“替代值”,因为在我们的遗留数据库中,有些枚举使用不可映射的值(例如,int时不以0开头,字符串类型时不能以枚举名称表示)。

以下功能可以很好地将枚举映射到其他名称:

代码语言:javascript
运行
复制
public class EnumAlternativeNameHelper {

  private static <T extends Enum<T> & EnumAlternativeName> T safeGetByAlternativeName(Class<T> enumClass, String alternativeName) {
    for ( T t : EnumSet.allOf(enumClass) ) {
      if ( t.getAlternativeName().equals(alternativeName) ) {
        return t;
      }
    }
    return null;
  }


  public static <T extends Enum<T> & EnumAlternativeName> Optional<T> getIfPresent(Class<T> enumClass, String alternativeName) {
    T t = safeGetByAlternativeName(enumClass,alternativeName);
    return Optional.fromNullable(t);
  }


  public static <T extends Enum<T> & EnumAlternativeName> T valueOf(Class<T> enumClass, String alternativeName) {
    T t = safeGetByAlternativeName(enumClass,alternativeName);
    return checkNotNull(t,"No alternative name of " + enumClass + " correspond to the provided alternative name = [" + alternativeName+"]");
  }


  public static <T extends Enum<T> & EnumAlternativeName> Optional<T> valueOfNullSafe(Class<T> enumClass, String alternativeName) {
    if ( alternativeName == null) {
      return Optional.absent();
    }
    return Optional.of( valueOf(enumClass,alternativeName) );
  }

}

由于我现在需要处理另一个顺序映射,所以我编写了如下所示的内容:

代码语言:javascript
运行
复制
public class EnumAlternativeValueHelper<EnumMappingInterface,ValueType> {

  private final Function<EnumMappingInterface,ValueType> mappingFunction;

  public EnumAlternativeValueHelper(Function<EnumMappingInterface, ValueType> mappingFunction) {
    Preconditions.checkArgument(mappingFunction != null);
    this.mappingFunction = mappingFunction;
  }


  private <EnumType extends Enum<EnumType> & EnumMappingInterface> EnumType safeGetByAlternativeValue(Class<EnumType> enumClass, ValueType value) {
    for ( EnumType enumInstance : EnumSet.allOf(enumClass) ) {
      if ( mappingFunction.apply(enumInstance).equals(value) ) {
        return enumInstance;
      }
    }
    return null;
  }

}

但是泛型声明<EnumType extends Enum<EnumType> & EnumMappingInterface>确实编译了,因为EnumMappingInterface:“这里期望的接口”。

我看到了这样的答案:Type parameter with multiple bounds

实际上,我的EnumMappingInterface是一个泛型类型,它将表示一个接口。它要么是EnumAlternativeName,要么是EnumAlternativeOrdinal,它们都定义了返回替代值的方法。

有什么解决办法吗?这样我就能实现我想做的事情了吗?谢谢

编辑:

EnumMappingInterface是一个泛型类型,所以它没有任何异议,但我应该将这个接口作为泛型类型传递:

代码语言:javascript
运行
复制
public interface EnumAlternativeName {

  String getAlternativeName();

  Function<EnumAlternativeName,String> GET_ALTERNATIVE_NAME = new Function<EnumAlternativeName,String>() {
    @Override
    public String apply(EnumAlternativeName input) {
      return input.getAlternativeName();
    }
  };

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-21 09:46:49

最后,通过定义抽象这两种情况的单个接口,可以很好地重写枚举名称()和序号():

代码语言:javascript
运行
复制
public interface EnumAlternativeValue<ValueType> {
  ValueType getAlternativeValue();
}

那我就能做到:

代码语言:javascript
运行
复制
public class EnumAlternativeValueHelper {


  private static <ValueType,EnumType extends Enum<EnumType> & EnumAlternativeValue<ValueType>> EnumType safeGetByAlternativeValue(Class<EnumType> enumClass, ValueType value) {
    for ( EnumType enumInstance : EnumSet.allOf(enumClass) ) {
      if ( enumInstance.getAlternativeValue().equals(value) ) {
        return enumInstance;
      }
    }
    return null;
  }


  public static <ValueType,EnumType extends Enum<EnumType> & EnumAlternativeValue<ValueType>> Optional<EnumType> getIfPresent(Class<EnumType> enumClass, ValueType value) {
    EnumType t = safeGetByAlternativeValue(enumClass,value);
    return Optional.fromNullable(t);
  }


  public static <ValueType,EnumType extends Enum<EnumType> & EnumAlternativeValue<ValueType>> EnumType valueOf(Class<EnumType> enumClass, ValueType value) {
    EnumType t = safeGetByAlternativeValue(enumClass,value);
    return checkNotNull(t,"No alternative value of " + enumClass + " correspond to the provided alternative value = [" + value+"]");
  }


  public static <ValueType,EnumType extends Enum<EnumType> & EnumAlternativeValue<ValueType>> Optional<EnumType> valueOfNullSafe(Class<EnumType> enumClass, ValueType value) {
    if ( value == null) {
      return Optional.absent();
    }
    return Optional.of( valueOf(enumClass,value) );
  }

  public static <ValueType> Function<EnumAlternativeValue<ValueType>,ValueType> getAlternativeValueFunction() {
    return new Function<EnumAlternativeValue<ValueType>,ValueType>() {
      @Override
      public ValueType apply(EnumAlternativeValue<ValueType> input) {
        return input.getAlternativeValue();
      }
    };
  }

}

而测试:

代码语言:javascript
运行
复制
public class EnumAlternativeValueHelperTest {


  private enum EnumUnderTest implements EnumAlternativeValue<String> {
    VALUE1("AlternativeName1"),
    VALUE2("AlternativeName2"),
    ;
    private final String alternativeName;
    private EnumUnderTest(String alternativeName) {
      this.alternativeName = alternativeName;
    }
    @Override
    public String getAlternativeValue() {
      return alternativeName;
    }
  }

  private enum EnumUnderTest2 implements EnumAlternativeValue<Integer> {
    VALUE1(1),
    VALUE2(2),
    ;
    private final int alternativeOrdinal;
    private EnumUnderTest2(int alternativeOrdinal) {
      this.alternativeOrdinal = alternativeOrdinal;
    }
    @Override
    public Integer getAlternativeValue() {
      return alternativeOrdinal;
    }
  }



  @Test
  public void getIfPresentReturnsValueTest() {
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest.class,"AlternativeName1") )
            .isEqualTo(Optional.of(EnumUnderTest.VALUE1));
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest2.class,1) )
            .isEqualTo(Optional.of(EnumUnderTest2.VALUE1));
  }
  @Test
  public void getIfPresentReturnsAbsent1Test() {
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest.class,"AlternativeNameUnknown") )
            .isEqualTo( Optional.<EnumUnderTest>absent() );
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest2.class,0) )
            .isEqualTo( Optional.<EnumUnderTest2>absent() );
  }
  @Test
  public void getIfPresentReturnsAbsentWhenNonAlternativeValueIsProvidedTest() {
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest.class, EnumUnderTest.VALUE1.name()) )
            .isEqualTo( Optional.<EnumUnderTest>absent() );
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest2.class, EnumUnderTest2.VALUE1.ordinal()) )
            .isEqualTo( Optional.<EnumUnderTest2>absent() );
  }
  @Test
  public void getIfPresentWhenBadAlternativeValueReturnsAbsentTest() {
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest.class,null) )
            .isEqualTo(Optional.<EnumUnderTest>absent());
    assertThat( EnumAlternativeValueHelper.getIfPresent(EnumUnderTest2.class,null) )
            .isEqualTo(Optional.<EnumUnderTest2>absent());
  }



  @Test
  public void valueOfReturnsValueTest() {
    assertThat( EnumAlternativeValueHelper.valueOf(EnumUnderTest.class, "AlternativeName1") )
            .isEqualTo( EnumUnderTest.VALUE1 );
    assertThat( EnumAlternativeValueHelper.valueOf(EnumUnderTest2.class, 1) )
            .isEqualTo( EnumUnderTest2.VALUE1 );
  }
  @Test(expected = NullPointerException.class)
  public void valueOfThrowsExceptionTest() {
    EnumAlternativeValueHelper.valueOf(EnumUnderTest.class, "AlternativeNameUnknown");
    EnumAlternativeValueHelper.valueOf(EnumUnderTest2.class, 0);
  }
  @Test(expected = NullPointerException.class)
  public void valueOfThrowsExceptionWhenBadAlternativeValueTest() {
    EnumAlternativeValueHelper.valueOf(EnumUnderTest.class, null);
    EnumAlternativeValueHelper.valueOf(EnumUnderTest2.class, null);
  }
  @Test(expected = NullPointerException.class)
  public void valueOfThrowsExceptionWhenNonAlternativeValueIsProvidedTest() {
    EnumAlternativeValueHelper.valueOf(EnumUnderTest.class, EnumUnderTest.VALUE1.name());
    EnumAlternativeValueHelper.valueOf(EnumUnderTest2.class, EnumUnderTest.VALUE1.ordinal());
  }


  @Test
  public void nullSafeValueOfReturnsValueTest() {
    assertThat(EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest.class, "AlternativeName1"))
            .isEqualTo(Optional.of(EnumUnderTest.VALUE1));
    assertThat(EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest2.class, 1))
            .isEqualTo(Optional.of(EnumUnderTest2.VALUE1));
  }
  @Test(expected = NullPointerException.class)
  public void nullSafeValueOfThrowsExceptionTest() {
    EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest.class, "AlternativeNameUnknown");
    EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest2.class, 1);
  }
  @Test
  public void nullSafeValueOfReturnsAbsentWhenBadAlternativeValueTest() {
    assertThat( EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest.class, null) )
            .isEqualTo(Optional.<EnumUnderTest>absent());
    assertThat( EnumAlternativeValueHelper.valueOfNullSafe(EnumUnderTest2.class, null) )
            .isEqualTo(Optional.<EnumUnderTest2>absent());
  }
  @Test(expected = NullPointerException.class)
  public void nullSafeValueOfThrowsExceptionWhenNonAlternativeValueIsProvidedTest() {
    EnumAlternativeValueHelper.valueOf(EnumUnderTest.class, EnumUnderTest.VALUE1.name());
    EnumAlternativeValueHelper.valueOf(EnumUnderTest2.class, EnumUnderTest.VALUE1.ordinal());
  }



  @Test
  public void alternativeValueFunctionTest() {
    assertThat(EnumAlternativeValueHelper.<String>getAlternativeValueFunction().apply(EnumUnderTest.VALUE1)).isEqualTo("AlternativeName1");
    assertThat(EnumAlternativeValueHelper.<Integer>getAlternativeValueFunction().apply(EnumUnderTest2.VALUE1)).isEqualTo(1);
  }
票数 0
EN

Stack Overflow用户

发布于 2013-05-17 17:17:26

当为泛型类型指定边界时,只能使用类和接口。不能将泛型类型绑定到其他泛型类型。在您的例子中,我建议您引入第三个标记接口EnumMappingInterface:

代码语言:javascript
运行
复制
public interface EnumMappingInterface {
}

并将其用作EnumAlternativeName和EnumAlternativeOrdinal接口的父接口:

代码语言:javascript
运行
复制
public interface EnumAlternativeName extends EnumMappingInterface {
    ...
}

在本例中,您有资格使用EnumMappingInterface作为EnumType泛型的第二个绑定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16613842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档