一个简单通用的enum工厂类

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/goldenfish1919/article/details/11745161

最新的代码在这里:https://mp.weixin.qq.com/s/yn1Fq1lpoY2QMre8AjY8PQ

扫码关注公众号【爪哇优太儿】

public interface BaseEnum<V> {
	public V getValue();
	public String getLabel();
}
public enum MonthEnum implements BaseEnum<Integer>{
	
	January(1, "1月"),  
    February(2, "2月"),  
    March(3, "3月");
    
    private int value;  
	private String label;
	
    private MonthEnum(int value, String label){  
        this.value = value; 
        this.label = label;
    }  
    
	@Override
	public Integer getValue() {
		return this.value;
	}

	@Override
	public String getLabel() {
		return this.label;
	}
}

 

public class EnumFactory {
	
	public static <T extends Enum<T> & BaseEnum<V>, V> T getByValue(Class<T> clazz, V id){
		EnumSet<T> set = EnumSet.allOf(clazz);
		for(T t : set){
			if(t.getValue().equals(id)){
				return t;
			}
		}
		return null;
	}
	
	public static <T extends Enum<T> & BaseEnum<V>, V> T getByLabel(Class<T> clazz, String label){
		EnumSet<T> set = EnumSet.allOf(clazz);
		for(T t : set){
			if(t.getLabel().equals(label)){
				return t;
			}
		}
		return null;
	}
}
public static void main(String[] args) {
		
		MonthEnum me = EnumFactory.getByValue(MonthEnum.class, 1);
		System.out.println(me);
		
		MonthEnum me2 = EnumFactory.getByLabel(MonthEnum.class, "1月");
		System.out.println(me2);
		
	}

今天忽然发现个非常恶心的问题,enum有一个的方法叫valueOf,参数是String,但是在找不到String对应的enum的时候,竟然会直接抛异常出来:

 

 

反编译enum的class文件可以看到会添加一个valueOf的方法:

 

   public static RuntimeSettingKey valueOf(String s)
    {
        return (RuntimeSettingKey)Enum.valueOf(test/RuntimeSettingKey, s);
    }

实际是调用父类的valueOf:

 

 public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum const " + enumType +"." + name);
    }

我擦,为啥不能返回一个null呢?

 

这会导致调用valueOf的地方必须得加一个try-catch!另一种变通的做法是,自己来遍历,不用valueOf方法,二者都够恶心的,really ugly!
------------------------------------------------------------------------------------------------------------

即使有了这样的工厂类,枚举写起来依然很费劲,加入抛弃枚举,该如何实现类似的功能呢?

 

public interface EnumAble<V> {//还是一样的接口
	public V getValue();
	public String getLabel();
}

 

public abstract class BaseEnum<T> implements EnumAble<T> {//这里我们用class而不是enum
	private T key;
	private String label;
	public BaseEnum(T key, String label){
		this.key = key;
		this.label = label;
		EnumFactory.add(this);
	}
	@Override
	public T getValue() {
		return this.key;
	}
	@Override
	public String getLabel() {
		return this.label;
	}
	@Override
	public String toString(){
		return getValue() +  "="  + getLabel();
	}
}
public class EnumFactory {
	
	@SuppressWarnings("rawtypes")
	private static ConcurrentHashMap<Class, Set> map = new ConcurrentHashMap<Class, Set>();
	
	public static <V, T extends BaseEnum<V>> void add(T t){
		@SuppressWarnings("unchecked")
		Set<BaseEnum<V>> list = map.get(t.getClass());
		if(list == null){
			list = new HashSet<BaseEnum<V>>();
			map.putIfAbsent(t.getClass(), list);
		}
		list.add(t);
	}
	
	@SuppressWarnings("unchecked")
	public static <V, T extends BaseEnum<V>> T getByValue(Class<T> clazz, V value){//接口还是一样的
		Set<BaseEnum<V>> list = map.get(clazz);
		if(list == null){
			try{
				Field[] fields = clazz.getFields();
				for(Field f : fields){
					f.get(null);
					break;
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			list = map.get(clazz);
		}
		for(BaseEnum<V> be : list){
			if(be.getValue().equals(value)){
				return (T)be;
			}
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	public static <T extends BaseEnum<V>, V> T getByLabel(Class<T> clazz, String label){//接口还是一样的
		Set<BaseEnum<V>> list = map.get(clazz);
		if(list == null){
			try{
				Field[] fields = clazz.getFields();
				for(Field f : fields){
					f.get(null);
					break;
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			list = map.get(clazz);
		}
		for(BaseEnum<V> be : list){
			if(be.getLabel().equals(label)){
				return (T)be;
			}
		}
		return null;
	}
}


实现的效果:

 

 

public class EnumFactoryTest {
	//这是我们的枚举类,这样就清爽多了啊!
	public static class MonthEnum extends BaseEnum<Integer>{
		public static MonthEnum January = new MonthEnum(1, "1月");
		public static MonthEnum February = new MonthEnum(2, "2月");
		public static MonthEnum March = new MonthEnum(3, "3月");
	    
	    public MonthEnum(int value, String label){  
	        super(value, label);
	    }  
	}
	//test
	public static void main(String[] args) {
		MonthEnum monthEnum = EnumFactory.getByValue(MonthEnum.class, 1);//接口还是一样的
		System.out.println(monthEnum);
	}
}

 

展开阅读全文

没有更多推荐了,返回首页