博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
枚举类型浅析
阅读量:6409 次
发布时间:2019-06-23

本文共 6510 字,大约阅读时间需要 21 分钟。

hot3.png

回头再写备注

1、枚举类就是class并且是一个不可被继承的final class,其枚举值都是public static final的。

2、既然枚举类是class其就会有构造、方法、数据域。但是枚举类的构造器有很大不同:首先,构造器只是在构造枚举值时使用;其次,构造器是private的,不允许为public(这样可以保证外部代码无法新构造枚举类的实例。这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。 但枚举类的方法和数据域可以允许外部访问)。

3、所有枚举类都继承了Enum的方法,下面我们详细介绍这些方法。 

 (1)  ordinal()方法: 返回枚举值在枚举类种的顺序。这个顺序根据枚举值声明的顺序而定。
 (2)  compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较象与指定对象的顺序。Enum中的compareTo返回的是两个枚举值的顺序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。
 (3)  values()方法: 静态方法,返回一个包含全部枚举值的数组。
 (4)  toString()方法: 返回枚举常量的名称。
 (5)  valueOf()方法: 这个方法和toString方法是相对应的,返回带指定名称的指定枚举类型的枚举常量。
 (6)  equals()方法: 比较两个枚举类对象的引用。

4、枚举类可以在switch语句中使用。

5.特定于常量的枚举方法

6.策略枚举(strategy enum)

package cn.com.imooc;//Enum type with data and behaviorpublic enum Planet {	MERCURY(3.302e+23,2.439e6),	VENUS(4.869E+24,6.052e6),	EARCH(5.975e+24,6.378e6),	MARS (6.419e+23,3.393e6),	JUPITER(1.899e+27,7.149e7),	STATURN(5.685e+26,6.027e7),	URANUS(8.683e+25,2.556e7),	NEPTUNE(1.024e+26,2.477e7);	private final double mass; //In kilograms	private final double radius; //In meters	private final double surfaceGravity; //In m/s^2		//Universal gravitational constant in m^3/kg s^2	private static final  double G = 6.67300E-11;		//Constructor	Planet(double mass,double radius){		this.mass = mass;		this.radius = radius;		surfaceGravity = G*mass/(radius*radius);	}		public double mass(){		return mass;	}		public double radius(){		return radius;	}		public double surfaceGravity()	{		return surfaceGravity;	}		public double surfaceWeight(double mass){		return mass*surfaceGravity; //F=ma	}}

测试:

package cn.com.test;import cn.com.imooc.Planet;public class WeightTable {	public static void main(String[] args) {				double earthWeight = Double.parseDouble("175");		double mass = earthWeight/Planet.EARCH.surfaceGravity();		for(Planet p : Planet.values()){			System.out.printf("Weight on %s is %f%n",p,p.surfaceWeight(mass));		}	}}

枚举类实现最基本的加减乘除:

package cn.com.imooc;//Enum type that switches on its own value -questionable/** * 枚举类实现最基本的加减乘除 * @author xiaomingtongxie * */public enum Operation {	PLUS,MINUS,TIMES,DIVIDE;		//Do the arithmetic op represented by this constant	double apply(double x, double y){		switch(this){			case PLUS: return x + y;			case MINUS: return x - y;			case TIMES: return x * y;			case DIVIDE: return x / y;		}		throw new AssertionError("Unkonwn op:" + this);	}}

枚举类型是编译安全类型,加入增加了新的运算枚举类,而没有在switch 中添加对应的条件,编译时不会报错,但运行时会出错。

于是有了,特定于常量的方法实现,优化代码如下:

package cn.com.imooc;//Enum type with constant-specific method implementationspublic enum Operation {	PLUS {		double apply(double x, double y) {			return x + y;		}	},	MINUS {		double apply(double x, double y) {			return x - y;		}	},	TIMES {		double apply(double x, double y) {			return x * y;		}	},	DIVIDE {		double apply(double x, double y) {			return x / y;		}	};	abstract double apply(double x, double y);}

枚举类中的抽象方法必须被它所有常量中的具体方法所覆盖,这样就不存在有编译时错误了。

package cn.com.imooc;//Enum type with constant-specific method implementationspublic enum Operation {	//枚举类中的抽象方法必须被它所有常量中的具体方法所覆盖	PLUS("+") {		double apply(double x, double y) {			return x + y;		}	},	MINUS("-") {		double apply(double x, double y) {			return x - y;		}	},	TIMES("*") {		double apply(double x, double y) {			return x * y;		}	},	DIVIDE("/") {		double apply(double x, double y) {			return x / y;		}	};		private final String symbol;	Operation(String symbol){this.symbol = symbol;}	@Override public String toString(){return symbol;}		abstract double apply(double x, double y);}

测试:

public static void main(String[] args) {		//Operation obj = Operation.MINUS;		double x = Double.parseDouble("2");		double y = Double.parseDouble("4");		for (Operation obj : Operation.values()) {			System.out.printf("%f %s %f = %f%n",x,obj,y,obj.apply(x, y));		}	}

在枚举类中覆盖toString,要考虑编写一个fromString方法,见定制的字符串表示法变回相应的枚举。

//Implementing a fromString method on an enum type	private static final Map
stringToEnum = new HashMap
(); static{ // Initialize map from constant name to enum constant for (Operation obj : values()) { stringToEnum.put(obj.toString(), obj); } } //Return Operation for string, or null if string is invalid public static Operation fromString(String symbol) { return stringToEnum.get(symbol); }

试图使每个常量都从自己的构造器将自身放入到map中,会导致编译时错误。枚举构造器不可以访问枚举的静态域,除了编译时常量域除外。

//实现工作日正常工资,双休加班工资是平时一半

package cn.com.imooc;//Enum tha switches on its value to share code-questionablepublic enum PayrollDay {	MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;	private static final int HOURS_PER_SHIFT = 8;	double pay(double hourWorked, double payRate) {		double basePay = hourWorked * payRate;		double overtimePay; // Calculate overtime pay		switch (this) {		case SATURDAY:		case SUNDAY:			overtimePay = hourWorked * payRate / 2;		default: // Weekdays			overtimePay = hourWorked <= HOURS_PER_SHIFT ? 0 : (hourWorked					* payRate / 2);			break;		}		return basePay + overtimePay;	}}

但是,如果添加了个特殊的枚举,代表假期天数的特殊值,但忘记添加相应的case.程序依然可以编译,但pay方法会悄悄地将假期的工资算成域常量工作日的相同。

每当添加一个枚举常量时,就强制选择一种加班报酬策略。

下面就是策略枚举的实现:

package cn.com.imooc;//The strategy enum patternpublic enum PayrollDay {	MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(			PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(			PayType.WEEKEND), SUNDAY(PayType.WEEKEND);	private final PayType payType;	PayrollDay(PayType payType) {		this.payType = payType;	};	double pay(double hoursWorked, double payRate){		return payType.pay(hoursWorked, payRate);	}	// The strategy enum type	private enum PayType {		WEEKDAY {			double overtimePay(double hours, double payRate) {				return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT)						* payRate / 2;			}		},		WEEKEND {			double overtimePay(double hours, double payRate) {				return hours * payRate / 2;			}		};		private static final int HOURS_PER_SHIFT = 8;		abstract double overtimePay(double hrs, double payRate);		double pay(double hoursWorked, double payRate) {			double basePay = hoursWorked * payRate;			return basePay + overtimePay(hoursWorked, payRate);		}	}}

这种思想就是将加班工资计算一道一个私有的嵌套枚举中,将这个策略枚举的实例转到PayrollDay枚举的构造器中。

当然,switch 还是有用的,比如说加减法倒置,乘除法倒置

//Switch on an enum to simulate a missing method	public static Operation inverse(Operation op){		switch (op) {		case PLUS: return Operation.MINUS;		case MINUS:return Operation.PLUS;		case TIMES:return Operation.DIVIDE;		case DIVIDE:return Operation.TIMES;		default: throw new AssertionError("Unkown op:" + op);		}	}

 

转载于:https://my.oschina.net/xiaomingnevermind/blog/821710

你可能感兴趣的文章
spring为什么推荐使用构造器注入
查看>>
基础数据类型之字典
查看>>
第七次作业
查看>>
Oracle中NVARCHAR2与VARCHAR2的区别
查看>>
php debug
查看>>
Ubuntu构建LVS+Keepalived高可用负载均衡集群【生产环境部署】
查看>>
温州动车事故中受伤的“我”,还好吗?
查看>>
lvm实现快速备份文件及数据库,lvm快照原理
查看>>
通常,人们会高估自己的学习能力
查看>>
设计模式之Factory Method(工厂方法)
查看>>
10K入职linux运维岗位小伙伴感谢信及面试经历分享
查看>>
Gartner:智能SOC/情报驱动的SOC的五大特征
查看>>
zookeeper入门之Curator的使用之几种监听器的使用
查看>>
[转]Reporting Service部署之访问权限
查看>>
innerxml and outerxml
查看>>
validform校验框架不显示错误提示
查看>>
flink 获取上传的Jar源码
查看>>
ZAB协议简介
查看>>
Spring Data JPA Batch Insertion
查看>>
swift Equatable 的缺省实现
查看>>