[英]How to implement an abstract function from a super class with an interface in java
[英]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;
}
請注意,循環具有對枚舉本身的引用。 因此,這需要將方法復制並粘貼到我想要使用它的所有枚舉中。 有什么建議嗎?
謝謝Victor
你不能以你想要的方式做到這一點。 你可以做的是有某種UTIL類的在其上有一個普遍mehod。
例如...
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
警告 - 在更復雜的系統中,這些類型的靜態util類有時候會有一些“代碼味道”,但我認為在你的情況下它很好。
對於Java6:
change each.name() => each.toString()
我建議使用像@Phil Anderson
這樣的@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
提到的,從性能的角度來看,這種方法有一定的缺點,因為異常的生成和拋出相當慢(請參閱Java異常有多慢? )。 但這只是一種情況,如果使用不正確的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
}
}
您可以使用具有靜態方法的接口來執行此操作:
public interface CanContainChannel {
static boolean contains(String channel) {
for (Channel c : Channel.values()) {
if (c.name().equals(channel)) {
return true;
}
}
return false;
}
}
你們兩個你的枚舉都可以實現這個接口來獲得這個方法,雖然我不確定你為什么要在你的Color枚舉上想要這樣的方法。
編輯:
在澄清問題時我會回答這個問題: 使用java泛型迭代枚舉值
使用反射,可以獲取枚舉常量。
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()
等接口。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.