我希望能够将枚举映射到“替代值”,因为在我们的遗留数据库中,有些枚举使用不可映射的值(例如,int时不以0开头,字符串类型时不能以枚举名称表示)。
以下功能可以很好地将枚举映射到其他名称:
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) );
}
}
由于我现在需要处理另一个顺序映射,所以我编写了如下所示的内容:
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是一个泛型类型,所以它没有任何异议,但我应该将这个接口作为泛型类型传递:
public interface EnumAlternativeName {
String getAlternativeName();
Function<EnumAlternativeName,String> GET_ALTERNATIVE_NAME = new Function<EnumAlternativeName,String>() {
@Override
public String apply(EnumAlternativeName input) {
return input.getAlternativeName();
}
};
}
发布于 2013-05-21 09:46:49
最后,通过定义抽象这两种情况的单个接口,可以很好地重写枚举名称()和序号():
public interface EnumAlternativeValue<ValueType> {
ValueType getAlternativeValue();
}
那我就能做到:
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();
}
};
}
}
而测试:
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);
}
发布于 2013-05-17 17:17:26
当为泛型类型指定边界时,只能使用类和接口。不能将泛型类型绑定到其他泛型类型。在您的例子中,我建议您引入第三个标记接口EnumMappingInterface:
public interface EnumMappingInterface {
}
并将其用作EnumAlternativeName和EnumAlternativeOrdinal接口的父接口:
public interface EnumAlternativeName extends EnumMappingInterface {
...
}
在本例中,您有资格使用EnumMappingInterface
作为EnumType
泛型的第二个绑定。
https://stackoverflow.com/questions/16613842
复制相似问题