使用通配符 Class<?> 从 Class 个枚举中检索枚举
Use Wildcard Class<?> to retrieve Enum from Class of Enums
我有以下代码
public interface SomeInterface { }
public class TestConstants {
public static <E extends Enum<E> & SomeInterface> E getEnumString(Class<E> clazz, String s){
for(E en : EnumSet.allOf(clazz)){
if(en.name().equalsIgnoreCase(s)){
return en;
}
}
return null;
}
public enum A implements SomeInterface {
V1,
V2,
V3;
}
public enum B implements SomeInterface {
V1,
V2,
V3;
}
// And so on.......
}
我可以在代码的其他地方调用 call
TestConstants.getEnumString(TestConstants.B.Class,"V2")
它会 return TestConstants.B.V2
一切都很好。
但我的问题是,如果我不知道实际的枚举怎么办 class 我会搜索
即
Class<?> enumClass
包含其中一个枚举,但我不知道是哪个。
现在我从 TestConstants class 外部的代码,我可以使用类似下面的代码
if (enumClass.equals(TestConstants.A.class)) {
TestConstants.getEnumString(TestConstants.A.class,value);
} else if (enumClass.equals(TestConstants.B.class)) {
TestConstants.getEnumString(TestConstants.B.class,value);
} else if (enumClass.equals(TestConstants.C.class)) {
// And so on....
但我真的很想将这段代码移到 TestConstants class 中。但我似乎做不到。
例如,如果我添加此功能
public static <E extends Enum<E> & SomeInterface> E fromUnknownClass(Class<?> enumClass, String name) {
if (enumClass.equals(TestConstants.A.class)) {
return TestConstants.fromString(TestConstants.A.class,name); <-- Compile error
} else if .......
.......
}
我得到以下编译错误
incompatible types: inference variable E has incompatible bounds equality constraints:
TestConstants.A upper bounds: E,java.lang.Enum<E>,SomeInterface
我在这里尝试的是否可行,或者是否有一些我不知道的泛型魔法?
你让你的生活变得不必要的艰难。在你的通用签名中
public static <E extends Enum<E> & SomeInterface> E getEnumString(Class<E> clazz, String s)
SomeInterface
的声明已过时。毕竟,无论特定 enum
是否实现 SomeInterface
,该方法都有效。它保证返回的类型与您传入的 class 匹配(读取:属于 E
类型)因此结果将实现 SomeInterface
if E
实施 SomeInterface
.
因此,如果您将方法更改为
public static <E extends Enum<E>> E getEnumString(Class<E> clazz, String s)
并传入 A.class
或 B.class
结果将分别为 A
或 B
类型,两者都实现 SomeInterface
。这甚至适用于调用者可能确实需要实现 SomeInterface
约束的通用上下文:
public <T extends Enum<T>&SomeInterface> void doSomethingWithSomeInterface(Class<T> cl) {
// works without getEnumString declaring SomeInterface ...
T t=getEnumString(cl, "V1");
}
但是,如果你传入一个Class<?>
,没有人能说结果是否会实现SomeInterface
,最好的验证方法是进行普通转换或instanceof
关于结果。
如果您按上述方式更改了签名,即使是未知类型也很容易使用:
Class<?> cl=A.class; // the "unknown" type Class<?>
Object obj=getEnumString(cl.asSubclass(Enum.class), "V1");
请注意,如果您不需要不区分大小写的匹配,有更简单的方法来获取 enum
常量。对于已知类型,您可以简单地调用,例如A.valueOf("V1")
,而对于泛型方法,它很简单:
public static <E extends Enum<E>> E getEnumString(Class<E> clazz, String s){
return Enum.valueOf(clazz, s);
}
这使得整个实用程序方法已过时,因为 Enum.valueOf(Class, String)
已经 是 该实用程序方法。
即使您需要不区分大小写的查找,您可能会认为 enum
常量通常全部大写,如果您遵守此约定,整个操作将变为:
Class<?> clazz=A.class; // simulate unknow type
String name="v1"; // for case insensitive match
// the operation:
Object aV1=Enum.valueOf(clazz.asSubclass(Enum.class), name.toUpperCase(Locale.ROOT));
SomeInterface si=(SomeInterface)aV1;
不需要额外的实用方法。
我有以下代码
public interface SomeInterface { }
public class TestConstants {
public static <E extends Enum<E> & SomeInterface> E getEnumString(Class<E> clazz, String s){
for(E en : EnumSet.allOf(clazz)){
if(en.name().equalsIgnoreCase(s)){
return en;
}
}
return null;
}
public enum A implements SomeInterface {
V1,
V2,
V3;
}
public enum B implements SomeInterface {
V1,
V2,
V3;
}
// And so on.......
}
我可以在代码的其他地方调用 call
TestConstants.getEnumString(TestConstants.B.Class,"V2")
它会 return TestConstants.B.V2
一切都很好。
但我的问题是,如果我不知道实际的枚举怎么办 class 我会搜索 即
Class<?> enumClass
包含其中一个枚举,但我不知道是哪个。
现在我从 TestConstants class 外部的代码,我可以使用类似下面的代码
if (enumClass.equals(TestConstants.A.class)) {
TestConstants.getEnumString(TestConstants.A.class,value);
} else if (enumClass.equals(TestConstants.B.class)) {
TestConstants.getEnumString(TestConstants.B.class,value);
} else if (enumClass.equals(TestConstants.C.class)) {
// And so on....
但我真的很想将这段代码移到 TestConstants class 中。但我似乎做不到。 例如,如果我添加此功能
public static <E extends Enum<E> & SomeInterface> E fromUnknownClass(Class<?> enumClass, String name) {
if (enumClass.equals(TestConstants.A.class)) {
return TestConstants.fromString(TestConstants.A.class,name); <-- Compile error
} else if .......
.......
}
我得到以下编译错误
incompatible types: inference variable E has incompatible bounds equality constraints:
TestConstants.A upper bounds: E,java.lang.Enum<E>,SomeInterface
我在这里尝试的是否可行,或者是否有一些我不知道的泛型魔法?
你让你的生活变得不必要的艰难。在你的通用签名中
public static <E extends Enum<E> & SomeInterface> E getEnumString(Class<E> clazz, String s)
SomeInterface
的声明已过时。毕竟,无论特定 enum
是否实现 SomeInterface
,该方法都有效。它保证返回的类型与您传入的 class 匹配(读取:属于 E
类型)因此结果将实现 SomeInterface
if E
实施 SomeInterface
.
因此,如果您将方法更改为
public static <E extends Enum<E>> E getEnumString(Class<E> clazz, String s)
并传入 A.class
或 B.class
结果将分别为 A
或 B
类型,两者都实现 SomeInterface
。这甚至适用于调用者可能确实需要实现 SomeInterface
约束的通用上下文:
public <T extends Enum<T>&SomeInterface> void doSomethingWithSomeInterface(Class<T> cl) {
// works without getEnumString declaring SomeInterface ...
T t=getEnumString(cl, "V1");
}
但是,如果你传入一个Class<?>
,没有人能说结果是否会实现SomeInterface
,最好的验证方法是进行普通转换或instanceof
关于结果。
如果您按上述方式更改了签名,即使是未知类型也很容易使用:
Class<?> cl=A.class; // the "unknown" type Class<?>
Object obj=getEnumString(cl.asSubclass(Enum.class), "V1");
请注意,如果您不需要不区分大小写的匹配,有更简单的方法来获取 enum
常量。对于已知类型,您可以简单地调用,例如A.valueOf("V1")
,而对于泛型方法,它很简单:
public static <E extends Enum<E>> E getEnumString(Class<E> clazz, String s){
return Enum.valueOf(clazz, s);
}
这使得整个实用程序方法已过时,因为 Enum.valueOf(Class, String)
已经 是 该实用程序方法。
即使您需要不区分大小写的查找,您可能会认为 enum
常量通常全部大写,如果您遵守此约定,整个操作将变为:
Class<?> clazz=A.class; // simulate unknow type
String name="v1"; // for case insensitive match
// the operation:
Object aV1=Enum.valueOf(clazz.asSubclass(Enum.class), name.toUpperCase(Locale.ROOT));
SomeInterface si=(SomeInterface)aV1;
不需要额外的实用方法。