需求描述:
假设有一个方法,入参为表示颜色的数字或者字符串,我们只针对特定的颜色执行一定的程序逻辑,要求1:表示红色;2:表示蓝色;3表示黄色,我们和调用我们接口的另一端程序做个约定,让他只能填入(1,2,3)几个值;
在没有正式应用枚举之前,我们可以自己写java类模拟枚举的功能:
通过接口的方式实现枚举功能:
package com.enumtest.learning;
/**
* 通过接口方式完成类似枚举类型的功能
*
* @author Administrator
*
*/
public class Color {
public final static ColorType RED =new Red(1);
public final static ColorType BLUE =new Blue(2);
public final static ColorType YELLOW =new Yellow(3);
/**
* 定义一个内部接口
* @author Administrator
*
*/
public static interface ColorType {
int getColor();
}
/**
* 接口的实现类为最终态的(final)
* @author Administrator
*
*/
final static class Red implements ColorType {
private int color = 0;
public Red(int color) {
this.color = color;
}
@Override
public int getColor() {
// TODO Auto-generatedmethod stub
return this.color;
}
}
final static class Blue implements ColorType {
private int color = 0;
public Blue(int color) {
this.color = color;
}
@Override
public int getColor() {
// TODO Auto-generatedmethod stub
return this.color;
}
}
final static class Yellow implements ColorType {
private int color = 0;
public Yellow(int color) {
this.color = color;
}
@Override
public int getColor() {
// TODO Auto-generatedmethod stub
return this.color;
}
}
}
测试上面定义的通过接口模拟的枚举功能
package com.enumtest.learning;
import com.enumtest.learning.Color.ColorType;
public class WithClass {
public void printColor(ColorType type){
switch (type.getColor()) {
case 1:
System.out.println("红色");
break;
case 2:
System.out.println("绿色");
break;
case 3:
System.out.println("黄色");
break;
default:
break;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
WithClass wc=new WithClass();
wc.printColor(Color.RED);
wc.printColor(Color.BLUE);
wc.printColor(Color.YELLOW);
}
}
总结:
我们将ColorType的子类设计为内部类,并且是final状态是为了防止外部程序进行集成,重载,可以看出,上述代码中printColor基本上没有参数类型判断的代码,只是一个分支流程的控制而已!我们距离目标越来越近了,但是不难发现,如果调用者自己实现了ColorType接口,那么它也可以浑水摸鱼将非法的类型传递进来,在5.0之前我们通过类的定义肯定是能够完全实现,只需要对上述代码进行一些简单的修改即可,比如说将参数类设计为不可继
承的,内部有很多实例变量,由于我们重点说明的是枚举,在这里我们将不在进行介绍,感兴趣的读者可以在网上查阅或者和我交流;
通过抽象类模拟枚举功能的实现
package com.enumtest.learning;
/**
* 基于抽象类模拟枚举功能的实现
* @author Administrator
*
*/
public abstract class Sex {
int value;
/**
* 构造函数私有化保证外部不能对该类进行实例化
* @param value
*/
private Sex(int value) {
this.value = value;
}
public final static Sex MAN=new Sex(1) {
@Override
public int getValue() {
// TODO Auto-generatedmethod stub
return this.value;
}
};
public final static Sex WOMAN=new Sex(2) {
@Override
public int getValue() {
// TODO Auto-generatedmethod stub
return this.value;
}
};
/**
* 定义一个获得属性值的抽象方法
* @return
*/
public abstract int getValue();
}
测试上面定义的通过接口模拟的枚举功能
package com.enumtest.learning;
public class WithSex {
public void printSex(Sex sex){
switch (sex.getValue()){
case 1:
System.out.println("男性");
break;
case 2:
System.out.println("女性");
break;
default:
break;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
WithSex sex=new WithSex();
sex.printSex(Sex.MAN);
sex.printSex(Sex.WOMAN);
}
}
正式通过枚举来实现这个功能
定义一个枚举
package com.enumtest.learning;
public enum ColorEnum{
RED,BLUE,YELLOW;
}
应用这个枚举:
package com.enumtest.learning;
public class WithEnum {
public void printColor(ColorEnum color){
switch (color) {
case RED:
System.out.println("红色");
break;
case BLUE:
System.out.println("蓝色");
break;
case YELLOW:
System.out.println("黄色");
break;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
WithEnum we=new WithEnum();
we.printColor(ColorEnum.RED);
we.printColor(ColorEnum.BLUE);
we.printColor(ColorEnum.YELLOW);
}
}
在printColor方法中,我们的入参只能为Color中的三个枚举值,否则在编译阶段就不能通过,这样就实现了在入参时期进行规则校验的目的;
枚举的构造函数,方法,以及字段
应用场景:
假设有这样一个枚举值Grade,其中A代表(90~100)B(80~89)C(70~79)D(60~69)E(0~59),我们除了用Grade控制入参之外,我们还想知道他代表的另外一层意思也就是数字的区间,如此这般,我们应该如何是好?
package com.enumtest.learning;
/**
* 枚举可以定义属性字段和方法以及构造方法
* @author Administrator
*
*/
public enum Grade {
A("90~100"),B("80~89"),C("70~79"),D("60~69"),E("0~59");
//枚举属性字段
private Stringvalue;
//枚举构造方法必须为private
private Grade(String value) {
this.value = value;
}
//枚举方法
public String getValue() {
returnvalue;
}
}
枚举测试:
package com.enumtest.learning;
public class GradeEnumTest {
public void printMessage(Grade grade){
System.out.println(grade.getValue());
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
GradeEnumTest ge=new GradeEnumTest();
ge.printMessage(Grade.A);
ge.printMessage(Grade.B);
ge.printMessage(Grade.C);
ge.printMessage(Grade.D);
ge.printMessage(Grade.E);
}
}
总结一下
Ø枚举类型的枚举值其实就是枚举类型的实例(静态)
Ø 枚举类型的构造函数必须是private的
枚举的抽象方法:
package com.enumtest.learning;
public enum GradeOfAbstract {
A("90~100"){
@Override
public String getLocalValue() {
// TODO Auto-generatedmethod stub
return"优秀";
}
},
B("80~89"){
@Override
public String getLocalValue() {
// TODO Auto-generatedmethod stub
return"良好";
}
},
C("70~79"){
@Override
public String getLocalValue() {
// TODO Auto-generatedmethod stub
return"中等";
}
},
D("60~69"){
@Override
public String getLocalValue() {
// TODO Auto-generatedmethod stub
return"差";
}
},
E("0~59"){
@Override
public String getLocalValue() {
// TODO Auto-generatedmethod stub
return"未及格";
}
};
private Stringvalue;
private GradeOfAbstract(String value) {
this.value = value;
}
public String getValue() {
returnvalue;
}
public abstract String getLocalValue();
}
测试:
package com.enumtest.learning;
public class AbstractEnumTest {
public static void printLocalValue(GradeOfAbstract grade){
System.out.println(grade.getLocalValue());
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
AbstractEnumTest.printLocalValue(GradeOfAbstract.A);
AbstractEnumTest.printLocalValue(GradeOfAbstract.B);
AbstractEnumTest.printLocalValue(GradeOfAbstract.C);
AbstractEnumTest.printLocalValue(GradeOfAbstract.D);
AbstractEnumTest.printLocalValue(GradeOfAbstract.E);
}
}
输出结果:
优秀
良好
中等
差
未及格
枚举类型可以实现接口或者集成抽象类
枚举类是final的,因为它不允许被继承,这也就解释了他必须实现抽象类中的全部抽象方法
简短的总结:
1) 枚举类型可以规范和约束运行时程序函数入参;
2) 枚举其实就是一个特殊的Class;
3) Object有的方法他都有,因为它是Object的子类;
4) 枚举类型其实是一个final类型的类,所以他不能被继承;
5) 枚举类型不仅可以定义枚举值,它还可以定义构造函数,方法以及属性字段;
6) 枚举类型的构造函数必须是私有的,这个不难理解,因为如果是可见的话,它就不能起到规范和约束的作用;
7) 枚举类型允许有抽象函数;
8) 枚举类型可以实现继承其他接口或者抽象类;
9) 每一个枚举常量都是public static final