簡體   English   中英

如何實現Java Enumeration Abstract類和接口?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM