• Guava Enums解决emue中的ValueOf找不到枚举的解决方法


    在 GitHub 上查看。

    问题

    在你知道输入有效的时候,使用Enum.valueOf非常棒。但是,如果传入无效的名称,那么将抛出异常。在某些情况下,这很好。不过,在通常情况下,我们宁愿忽略异常并返回null。

    log.debug("Running valueOf");
    for (String name : names) {
        try {
            log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.valueOf(name)));
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
        }
    }
    2017-02-22 14:46:38.556 [main] DEBUG c.s.examples.common.EnumLookup - Running valueOf
    2017-02-22 14:46:38.804 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.808 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:154)
    拙劣的实现

    很不幸的是,以下两种方法在代码库中出现得是这么的频繁。反面例子,勿学。

    Enum.valueOf With Try Catch(劣)

    这种拙劣的做法最常见于初学者。异常不应该用于控制流,并且这样可能会有一些性能影响。不要偷懒。你必须用正确的方式去做。

    /*
     * Please don't do this! Using try / catch for
     * control flow is a bad practice.
     */
    public static CardSuit trycatchValueOf(String name) {
        try {
            return CardSuit.valueOf(name);
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
            return null;
        }
    }
    log.debug("Running trycatchValueOf");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.trycatchValueOf(name)));
    }
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running trycatchValueOf
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.trycatchValueOf(EnumLookup.java:89)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:171)
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    通过迭代查找(劣)

    这种方法也很常见(见这里),但至少程序员知道不能用try/catch来捕获异常。那么,这种方法有什么问题呢?没错,它会迭代所有枚举,直到找到匹配的枚举或返回null——最坏的情况下需要n次,其中n就是枚举值的数量。有些人可能会认为这微不足道,这是过早优化了而已。但是,数据结构和算法是CS基础。使用Map而不是迭代集合要省力得多。这会大大提高性能吗?不,但它是一个很好的习惯。在面试候选人时,你会对线性复杂度搜索算法感到满意吗?此时,你不应该让这样的代码审查通过。

    /*
     * Please don't do this! It is inefficient and it's
     * not very hard to use Guava or a static Map as an index.
     */
    public static CardSuit iterationFindByName(String name) {
        for (CardSuit suit : CardSuit.values()) {
            if (name.equals(suit.name())) {
                return suit;
            }
        }
        return null;
    }
    log.debug("Running iteration");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.iterationFindByName(name)));
    }
    2017-02-22 14:46:38.808 [main] DEBUG c.s.examples.common.EnumLookup - Running iteration
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null

    我们可以用谷歌的Guava Enums解决ValueOf中找到枚举的异常:
    Enums提供了几个操作Enum的便利方法

    常用方法

    Field getField(Enum<?> enumValue): 返回变量名为enumValue变量值的Field

    <T extends Enum<T>> Function<String, T> valueOfFunction(Class<T> enumClass): 返回一个可以将enum名字字符串转换成指定类型的enum的, 如果enum不存在时,Function将返回null

    Optional<T> getIfPresent(Class<T> enumClass, String value): 使用Enum.valueOf()来返回指定名称和class的Enum的Optional,如果不存在则返回Absent, 常见用法Enums.getIfPresent(Country.class, countryInput).or(Country.DEFAULT)

    代码:

    package simplefactory;
    
    import com.google.common.base.Enums;
    
    import java.lang.reflect.InvocationTargetException;
    
    
    /**
     * @author 黄豪强
     * @create 2019/7/24 16:11
     */
    public class RealObjectImpl implements RealObject {
        public Object select(String name) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
            StarEmue aa = Enums.getIfPresent(StarEmue.class, name).or(StarEmue.NoStar);
            String a = aa.getS();
            Class star = Class.forName(a);
            return star.newInstance();
        }
    }

    枚举:

    package simplefactory;
    
    /**
     * @author 黄豪强
     * @create 2019/7/25 9:50
     */
    public enum StarEmue {
    
        James("simplefactory.James"), Jodren("simplefactory.Jodren"),NoStar("simplefactory.NoStar");
        private String s;
    
        private StarEmue(String s) {
            this.s = s;
        }
    
        public String getS() {
            return s;
        }
    
        public void setS(String s) {
            this.s = s;
        }
    }


  • 相关阅读:
    dubbo+zookeeper注册服务报错问题:No service registed on zookeeper
    悲观锁和乐观锁的区别,它们是怎么实现
    cookie和session的区别,分布式环境怎么保存用户状态
    深入理解Java接口和抽象类
    Java中堆内存和栈内存详解
    Java基础梳理(一)
    Spring的@Transactional注解详细用法
    SpringBoot学习笔记(一)基础
    项目实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错,eclipse中配置lombok
    有依赖的背包问题-购物单
  • 原文地址:https://www.cnblogs.com/socketqiang/p/11243151.html
Copyright © 2020-2023  润新知