zoukankan      html  css  js  c++  java
  • 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;
        }
    }


  • 相关阅读:
    误操作 rpm -e --nodeps zlib
    Raid阵列之简单介绍
    GpG使用指南
    hadoop系统的端口
    网站日志流量复杂分析
    Flume在企业大数据仓库架构中位置及功能
    Hue的安装与部署
    Hive中的数据倾斜
    Hive的三种Join方式
    如何每日增量加载数据到Hive分区表
  • 原文地址:https://www.cnblogs.com/socketqiang/p/11243151.html
Copyright © 2011-2022 走看看