Effective Java —— 枚举篇 精华总结

JAVA推荐使用枚举代替int

1 枚举提供了类型安全检测
2 枚举隔离了使用的类和枚举类型,使增加和重排无需重新编译
3 本质上是单元素枚举,final类型,不支持扩展(继承),但是可以自由使用接口和方法。
4 便于理解,维护
5 绝对安全的单例类型(相对于双重锁,无法被反序列化创造多个实例)

Android 不建议使用枚举的原因

1 手机内存资源有限,ENUM将会增大最终的DEX文件,大约是Integer常量的13倍,大量使用会影响程序性能。
2 虚拟机加载枚举类,并且实例化所有的枚举项,并且这些枚举实例的内存无法回收,而且枚举是单例,如果自定义的枚举类中包含了大块内存的引用,也可能会带来内存泄露。

实例域代替系数

永远不要根据枚举的序数导出与它关联的值(ordinal()方法虽然从0开始,但是当常量重排序时会混乱),而是要将它保存在一个实例域中:

public enum Ensemble {

SOLO(1), DUET(2), TRIO(3),  QUARTET(4), QUINTET(5),

private final int numberOfMusicians;

Ensemble(int size ) { this.numberOfMusicians = size; }

public int numberOfMusicians() { return numberOfMusicians;}

}

EnumSet代替位域

位域:text.applyStyles(STYLE_BOLD | STYLE_ITALIC);

位域表示的缺陷:位域以数字形式打印时,翻译位域比翻译简单的int枚举常量要困难得多;要遍历位域表示的所有元素也没有很容易的方法。

EnumSet:

public class Text {
    public enum Style {BOLD , ITALIC , UNDERLINE , STRIKETHROUGH}

// Any Set could be passed in , but EnumSet is clearly best

public void applyStyles(Set<Style> styles) { ... }
}

使用:text.applyStyles(EnumSet.of(Style.BOLD , Style.ITALIC));

EnumSet缺点:即截止Java 1.6发行版本,他都无法创建不可变的EnumSet,但是这一点很可能在即将出现的版本中得到修正。同时,可以用Collections.unmodifiableSet将EnumSet封装起来,但是间接性和性能会受到影响。

用EnumMap代替序数索引

EnumMap优点:
1 结构清晰,如果用索引,无法知道索引与对应集合的关系)
2 安全,相对于索引作为key,当修改对应集合时,如果未修改索引可能引发重大问题。

示例:

public enum Phase {
    SOLID, LIQUID, GAS;

    public enum Transition {
        MELT(SOLID,LIQUID), FREEZE(LIQUID, SOLID),
        BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID),
        SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);

        private final Phase src;
        private final Phase dst;

        Transition(Phase src, Phase dst) {
            this.src = src;
            this.dst = dst;
        }

        private static final Map<Phase, Map<Phase, Transition>> m =
                new EnumMap<Phase, Map<Phase, Transition>>(Phase.class);
        static {
            for(Phase p : Phase.values())
                m.put(p, new EnumMap<Phase, Transition>(Phase.class));
            for(Transition t : Transition.values())
                m.get(t.src).put(t.dst, t);
        }

        public static Transition from(Phase src, Phase dst) {
            return m.get(src).get(dst);
        }
    }
}

用接口模拟可伸缩的枚举

枚举为final,无法通过继承扩展,但可以使用接口方式扩展

public interface Operation {
    double apply(double x,double y);
}

public enum BasicOperation implements Operation {   
    PLUS("+"){      
        public double apply(double x, double y) {           
            return x + y;
        }
    },
    MINUS("-"){ 
        public double apply(double x, double y) {           
            return x - y;
        }
    };  
    private final String symbol;
    BasicOperation(String symbol) {
        this.symbol = symbol;
    }   
    @Override
    public String toString(){
        return symbol;
    }
}
public enum ExtendedOperation implements Operation{
    Exp("^"){
        public double apply(double x,double y){
            //次幂计算
            return Math.pow(x, y);
        }
    },
    REMAINDER("%"){
        public double apply(double x,double y){
            return x % y;
        }
    };

    private final String symbol;
    ExtendedOperation(String symbol) {
        this.symbol = symbol;
    }
    @Override
    public String toString(){
        return symbol;
    }
}

猜你喜欢

转载自blog.51cto.com/13952501/2310880