你如何实现一个Java Enumeration Abstract class 和接口?
How do you implement a Java Enumeration Abstract class and interface?
我有以下问题。
我在 java.
中有一个包含不同枚举 类 的包
在添加所有枚举通用的新方法时避免重复自己的正确方法是什么?
我的问题:
channel.java
public enum Channel {
channel1, channel2;
}
color.java
public enum color{
color1, color2;
}
两者都应该使用的方法:
public static boolean contains(String channel) {
for (Channel c : Channel.values()) {
if (c.name().equals(channel)) {
return true;
}
}
return false;
}
请注意,循环引用了枚举本身。因此,这将需要将该方法复制并粘贴到我要使用它的所有枚举中。
有什么建议吗?
谢谢
维克多
您可以使用带有静态方法的接口来执行此操作:
public interface CanContainChannel {
static boolean contains(String channel) {
for (Channel c : Channel.values()) {
if (c.name().equals(channel)) {
return true;
}
}
return false;
}
}
你们两个枚举都可以实现这个接口来获得这个方法,虽然我不确定你为什么要在你的 Color 枚举上使用这样的方法。
编辑:
关于问题的澄清我这个问题对你有帮助:
Iterate enum values using java generics
不幸的是,你不能完全按照你想要的方式去做。您可以做的是拥有某种具有通用方法的实用程序class。
例如...
public class EnumUtils {
public static boolean contains(Enum[] enumValues, String nameToCheck) {
for(Enum each : enumValues) {
if(each.name().equals(nameToCheck)) {
return true;
}
}
return false;
}
}
那你就可以这样用了...
System.out.println(EnumUtils.contains(Channel.values(), "channel1")); // TRUE
System.out.println(EnumUtils.contains(Color.values(), "octarine")); // FALSE
警告 - 在更复杂的系统中,这些静态实用程序 classes 有时有点 "code-smell" 但我认为你的情况很好。
对于Java6:
change each.name() => each.toString()
我建议使用像 @Phil Anderson
提到的实用方法。我只会将其更改为通用模式:
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
try {
T foundEnum = Enum.valueOf(clazz, name);
// name matches to one of enum values, do something with it
} catch (IllegalArgumentException e) {
// name doesn't matches to any of enum values
}
}
在包含语义的情况下可能如下所示:
public static <T extends Enum<T>> boolean contains(Class<T> clazz, String name) {
try {
Enum.valueOf(clazz, name);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
更新:
正如 @phil-anderson
提到的,从性能的角度来看,这种方法有一定的缺点,因为异常的生成和抛出非常慢(参见 How slow are Java exceptions?)。但这只是一种情况,如果使用不正确的 name
值调用方法。
所以,在这种情况下,您可以使用这种模式:
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
for (T each : clazz.getEnumConstants()) {
if (each.name().equals(name)) {
// name matches to one of enum values, do something with it
}
}
// name doesn't matches to any of enum values
}
此外,如果性能起着重要作用,尤其是如果枚举包含大量值,则迭代(也许)所有这些值效率不高。解决方案可能是对枚举使用惰性哈希映射并通过哈希码获取值。例如:
@SuppressWarnings("unchecked")
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
Map<String, Enum<?>> enumMap = enumsMap.get(clazz);
if (enumMap == null) {
enumMap = new HashMap<String, Enum<?>>();
for (T t : clazz.getEnumConstants()) {
enumMap.put(t.name(), t);
}
enumsMap.put(clazz, enumMap);
}
T t = (T) enumMap.get(name);
if (t != null) {
// name matches to one of enum values, do something with it
} else {
// name doesn't matches to any of enum values
}
}
通过反射可以获取枚举常量。
enum E {
i("unu"), ii("du"), iii("tri"), iv("kvar");
public final String name;
E(String name) {
this.name = name;
}
}
public static void main(String[] args) {
// Normally in Java 8 for a concrete enum:
final String sought = "tri";
boolean found = Stream.of(E.values()).anyMatch((c) -> c.name.equals(sought));
// A generic function:
System.out.println("okay: "
+ find(E.class, (c) -> c.name.equals(sought)));
System.out.println("fails: "
+ find(E.class, (c) -> c.name.equals("prtl")));
}
public static <T extends Enum<?>> boolean find(Class<T> clazz,
Predicate<T> predicate) {
return Stream.of(clazz.getEnumConstants()).anyMatch(predicate);
}
因为要访问一个字段,传递整个谓词更容易。
在 java 7 下,通常会更紧凑(没有 Stream)并且需要一个用于 getName()
等的接口。
我有以下问题。 我在 java.
中有一个包含不同枚举 类 的包在添加所有枚举通用的新方法时避免重复自己的正确方法是什么?
我的问题:
channel.java
public enum Channel {
channel1, channel2;
}
color.java
public enum color{
color1, color2;
}
两者都应该使用的方法:
public static boolean contains(String channel) {
for (Channel c : Channel.values()) {
if (c.name().equals(channel)) {
return true;
}
}
return false;
}
请注意,循环引用了枚举本身。因此,这将需要将该方法复制并粘贴到我要使用它的所有枚举中。 有什么建议吗?
谢谢 维克多
您可以使用带有静态方法的接口来执行此操作:
public interface CanContainChannel {
static boolean contains(String channel) {
for (Channel c : Channel.values()) {
if (c.name().equals(channel)) {
return true;
}
}
return false;
}
}
你们两个枚举都可以实现这个接口来获得这个方法,虽然我不确定你为什么要在你的 Color 枚举上使用这样的方法。
编辑:
关于问题的澄清我这个问题对你有帮助: Iterate enum values using java generics
不幸的是,你不能完全按照你想要的方式去做。您可以做的是拥有某种具有通用方法的实用程序class。
例如...
public class EnumUtils {
public static boolean contains(Enum[] enumValues, String nameToCheck) {
for(Enum each : enumValues) {
if(each.name().equals(nameToCheck)) {
return true;
}
}
return false;
}
}
那你就可以这样用了...
System.out.println(EnumUtils.contains(Channel.values(), "channel1")); // TRUE
System.out.println(EnumUtils.contains(Color.values(), "octarine")); // FALSE
警告 - 在更复杂的系统中,这些静态实用程序 classes 有时有点 "code-smell" 但我认为你的情况很好。
对于Java6:
change each.name() => each.toString()
我建议使用像 @Phil Anderson
提到的实用方法。我只会将其更改为通用模式:
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
try {
T foundEnum = Enum.valueOf(clazz, name);
// name matches to one of enum values, do something with it
} catch (IllegalArgumentException e) {
// name doesn't matches to any of enum values
}
}
在包含语义的情况下可能如下所示:
public static <T extends Enum<T>> boolean contains(Class<T> clazz, String name) {
try {
Enum.valueOf(clazz, name);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
更新:
正如 @phil-anderson
提到的,从性能的角度来看,这种方法有一定的缺点,因为异常的生成和抛出非常慢(参见 How slow are Java exceptions?)。但这只是一种情况,如果使用不正确的 name
值调用方法。
所以,在这种情况下,您可以使用这种模式:
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
for (T each : clazz.getEnumConstants()) {
if (each.name().equals(name)) {
// name matches to one of enum values, do something with it
}
}
// name doesn't matches to any of enum values
}
此外,如果性能起着重要作用,尤其是如果枚举包含大量值,则迭代(也许)所有这些值效率不高。解决方案可能是对枚举使用惰性哈希映射并通过哈希码获取值。例如:
@SuppressWarnings("unchecked")
public static <T extends Enum<T>> void some_method(Class<T> clazz, String name) {
Map<String, Enum<?>> enumMap = enumsMap.get(clazz);
if (enumMap == null) {
enumMap = new HashMap<String, Enum<?>>();
for (T t : clazz.getEnumConstants()) {
enumMap.put(t.name(), t);
}
enumsMap.put(clazz, enumMap);
}
T t = (T) enumMap.get(name);
if (t != null) {
// name matches to one of enum values, do something with it
} else {
// name doesn't matches to any of enum values
}
}
通过反射可以获取枚举常量。
enum E {
i("unu"), ii("du"), iii("tri"), iv("kvar");
public final String name;
E(String name) {
this.name = name;
}
}
public static void main(String[] args) {
// Normally in Java 8 for a concrete enum:
final String sought = "tri";
boolean found = Stream.of(E.values()).anyMatch((c) -> c.name.equals(sought));
// A generic function:
System.out.println("okay: "
+ find(E.class, (c) -> c.name.equals(sought)));
System.out.println("fails: "
+ find(E.class, (c) -> c.name.equals("prtl")));
}
public static <T extends Enum<?>> boolean find(Class<T> clazz,
Predicate<T> predicate) {
return Stream.of(clazz.getEnumConstants()).anyMatch(predicate);
}
因为要访问一个字段,传递整个谓词更容易。
在 java 7 下,通常会更紧凑(没有 Stream)并且需要一个用于 getName()
等的接口。