栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Effective java 总结5 - 枚举和注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Effective java 总结5 - 枚举和注解

Effective java 总结5 - 枚举和注解

java两种特殊的引用类型

  • 类 :枚举类型
  • 接口 :注解类型
第34条 用enum代替int常量

枚举类型:由一组固定的常量组成合法值的类型

java的枚举类型是功能齐全的类,本质还是int值, 通过公有的静态final域为每个枚举常量导出一个实例。枚举类型没有可以访问的构造器,是真正的final类,是实例受控的。

枚举类型允许添加任意的方法和域,并实现任意的接口(提供了所有的Object方法的高级实现,实现了Comparable、Serializable接口…)

为了将数据与枚举常量联系起来,需要声明实例域(均为final),并编写构造器

public enum Demo {
    A(1, 2),
    B(3, 4),
    C(1, 1);
    
    private final int i1;
    private final int i2;
    
    Demo(int i1, int i2){
        this.i1 = i1;
        this.i2 = i2;
    }
    
    public int sum(){
        return i1 + i2;
    }
}

Enum类的常用方法

方法描述
values()以数组的形式返回枚举类型的所有成员
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序
ordinal()获取枚举成员的索引位置
toString()返回每个枚举值的声明名称

如果一个枚举具有普遍适应性,则应该成为顶层类, eg: java.math.RoundingMode(十进制小数舍入模式)

特定与常量的方法实现

public enum Operation{
    PLUS("+") {
        public double apply(double x, double y){return x + y;}
    },
    MINUS("-") {
        public double apply(double x, double y){return x - y;}
    },
    TIMES("*") {
        public double apply(double x, double y){return x * y;}
    },
    DIVIDE("/") {
        public double apply(double x, double y){return x / y;}
    };
    
    private final String symbol;
    Operation(String symbol){
        this.symbol = symbol;
    }
    public abstract double apply(double x, double y); // 必须是抽象的,每个枚举实例都要实现  
}

策略枚举

public enum PayrollDay{
    MONAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
    SATURDAY(PayType.WEEKEND), SUNDAY(Paytype.WEEKEND);
    
    private final PayType payType;
    
    payrollDay(PayType payType) { 
        this.payType = payType;
    }
    PayrollDay(){this(PayType.WEEKDAY)}
    
    private enum PayType{ // 私有的嵌套枚举类
        WEEKDAY{
            int overtimePay(int mins, int payRate){
                return ...
            }
        },
        WEEKEND{
            int overtimePay(int mins, int payRate){
                return ...
            }
        };
        abstract int overtimePay(int mins, int payRate);
        private static final int MINS_PER_SHIFT = 8 * 60;
        
        int pay(int mins, int payRate){
            int basePay = mins * payRate;
            return basePay + overtimePay(mins, payRate);
        }
    }
}
  • 每当需要一组固定的常量,并且在编译时就知道其成员的时候,就应该使用枚举
  • 每个枚举常量都需要不同的行为,考虑特定于常量的方法
  • 多个但非所有枚举常量同时共享相同的行为需要考虑策略枚举

第35条 用实例域代替序数

永远不要根据实例的序数导出与它关联的值

// 错误示例  // 问题在于如果修改枚举常量增加或减少,则ordinal()会变,可能造成错误使用
public enum NoDoThis{
    A, B, C;
    public int getOrder() { return ordinal() + 1;}
}
// 正确示例
public enum DoThis{
    A(1), B(11), C(333);
    
    private final int order;
    DoThis(int order) { this.order = order};
    public int getOrder() {return order;}
}

一般不使用ordinal(), 它是设计用于像 EnumSet 和 EnumMap 这种基于枚举的通用数据结构


第36条 用EnumSet代替位域

用 OR 位运算符将几个常量合并到一个集合中,称作位域

// 位域
public class Text{
	public static final int STYLE_BOLD = 1 << 0;
    public static final int STYLE_ITALIC = 1 << 1;
    ...
    public void applyStyles(int styles){...}
}
text.applyStyles(STYLE_BOLD | STYLE_ITALIC);

// EnumSet
public class Text{
    public enum Style{
        BOLD, ITALIC, UNDERLINE, STRIKETHROUGH
    }
    
    public void applyStyles(Set