简体   繁体   English

Java枚举自动生成getInstance方法?

[英]Java enum autogenerate getInstance method?

Lets say I have the following java enum 可以说我有以下java枚举

public enum Color {
  RED(10),
  GREEN(22),
  BLUE(33);

  private int value;

  Color(int value) {
    this.value = value;
  }

  public int intValue() {
    return value;
  }
}

In order to be able to obtain a color instance by a given integer value I need to add method like this: 为了能够通过给定的整数值获取颜色实例,我需要添加如下方法:

public static Color getInstance(int value) {
  switch (value) {
    case 10: return RED;
    case 22: return GREEN;
    case 33: return BLUE;
    default: throw new IllegalArgumentException("Invalid color value");
  }
}

Is it possible this method to be autogenerated from the IDE? 是否有可能从IDE自动生成此方法? (Preferably IntelliJ)? (最好是IntelliJ)?

Instead of repeating the code in every enum , you may implement a central utility method for all kinds of enums with an int value. 您可以为具有int值的所有类型的枚举实现中央实用程序方法,而不是在每个enum中重复代码。 This is possible since enum s can implement interfaces, hence you can define a uniform way of accessing the int value: 这是可能的,因为enum可以实现接口,因此您可以定义访问int值的统一方式:

public interface IntValued {
    int intValue();
}
/** get the particular {@link IntValued} {@code enum} constant. */
public static <T extends Enum<T>&IntValued> T get(Class<T> type, int value) {
    return type.cast(GET.get(type).apply(value));
}
private static ClassValue<IntFunction<Enum>> GET = new ClassValue<IntFunction<Enum>>() {
    protected IntFunction<Enum> computeValue(Class<?> type) {
        return prepare(type);
    }
};
// invoked only once per enum type
static IntFunction<Enum> prepare(Class<?> type) {
    Enum[] values=type.asSubclass(Enum.class).getEnumConstants();
    if(values.length==0) return i -> null;
    IntSummaryStatistics s=Arrays.stream(values)
        .mapToInt(o -> ((IntValued)o).intValue())
        .summaryStatistics();
    int min=s.getMin(), max=s.getMax();
    if((max-min+1)<s.getCount()*2) {
        Enum[] linear=new Enum[max-min+1];
        for(Enum e: values) linear[((IntValued)e).intValue()-min]=e;
        return i -> i<min||i>max? null: linear[i-min];
    }
    Map<Integer, Enum> map = Arrays.stream(values).collect(
        Collectors.toMap(o -> ((IntValued)o).intValue(), Function.identity()));
    return map::get;
}

This uses ClassValue , a JRE provided way of associating custom meta data to a class. 这使用ClassValue ,这是一种将自定义元数据与类相关联的JRE方法。 ClassValue takes care of invoking the initialization code only once and still allows garbage collection/ class unloading. ClassValue负责调用初始化代码一次,仍然允许垃圾收集/类卸载。 The code above dynamically determines which lookup structure to use. 上面的代码动态地确定要使用的查找结构。 If the int values of a particular enum type are dense, it uses an array, otherwise it resorts to a Map . 如果特定enum类型的int值是密集的,则它使用数组,否则它将转换为Map

You can use it as follows: 您可以按如下方式使用它:

public enum Color implements IntValued {
    RED(10),
    GREEN(22),
    BLUE(33);

    private int value;

    Color(int value) {
      this.value = value;
    }

    public int intValue() {
      return value;
    }
}

Color color=get(Color.class, 22);
System.out.println(color);

Note that this solution, unlike generated switch statements, does not break if these int values are changed. 请注意,与生成的switch语句不同,此解决方案如果更改了这些int值,则不会中断。

If you are using Java 8 you can make use of default methods in interface to add functionality to any class - even enum s. 如果您使用的是Java 8,则可以在interface使用default方法来为任何类添加功能 - 甚至是enum

Take a look here where I add a reverse-lookup to an enum just by making it implement ReverseLookup . 看看这里我只是通过implement ReverseLookup来向enum添加反向查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM