从普通类的角度理解java的enum类型,用自定义类来模拟实现enum类的功能

enum定以的类型就是一个类,一个类,一个类。重要的事情说三遍。用javac编译好enum类型后,会看到一个xxx.class文件,表明enum类型也是一个类。

本文中,我们用一个普通类去定义常量,模拟、对比用enum定义的常量,可以帮我们更容易理解enum类型是如何工作的。

enum跟class关键字一样,都是定义了一个类,只是这个类有点特殊,他有以下特点:

1. enum定义的这个类里边定义了一组常量(static final),并且每个常量的类型都是enum定义的这个类本身,并且这些常量都指向enum定义的这个类(或其子类)的对象(这些常量本身是对象的引用)。

2. 我们用普通类定义的的静态成员变量,长这样:

class Day{
    private int dayOfWeek;

	public static final Day Monday = new Day(0);
    public static final Day Tuestday= new Day(1);
    ...
    Day(int day){
        this.dayOfWeek = day;
    }
    ...
}

而用enum定义的类中定义的常量是下边这样:

enum Day{
    Monday, Tuesday, Wendesday ....;
}

 其实他们是一回事。enum定义的类,里边的常量,你不需要显示的加上static final,然后用new创建一个对象赋给这些静态常量,这一切都由编译器给你做好。这就相当于一个语法糖。上边enum类里边定义的Monday, Tuesday, Wendesday等静态成员变量,实际上也会关联一个数字,只是不需要我们显式的通过new Day(0)或者Monday(0)来指定,编译器会帮我们搞定。

但有时候,我们希望用enum定义的常量,不仅仅是一个简单的常量,我们希望它关联更多的数据,这时我们会使用类似下边的语法,就是往enum定义的类里边添加更多的非静态成员变量:

enum Day{
    //每天上的课程
    private final String[] courses;
    
    Monday("语文","数学","英语"), 
    Tuesday("体育","数学","英语"), 
    Wendesday("化学","物理","英语") 
    ....;

    CoursesOfDay(String ... courses){
      this.courses = courses;
    }
}

我们可以看到在这个例子中, Monday等常量不仅仅隐式的关联的一个整数变量,我们还显式的在这个类里边定义了一个数组,表示每天的课程表。如果你愿意,甚至还可以定义更多的非静态成员变量,这样每一个常量(实际上是一个该enum类的对象的引用)就可以关联到更多的数据。使用常量时,可以像这样:

System.out.println(Day.Monday.getCourses());

3. 这个用enum定义的类可以有多个非静态成员变量,但都必须是immutable的,也就是用final修饰。比如上边我们的courses变量用final修饰。

4. enum类的构造方法私有

5. enum定以的类默认拥有public的values()方法,返回的是一个数组,数组里边包含了所有我们之前定义的常量。 

6. 这些常量的默认的toString()方法是打印跟常量同名的字符串,比如打印Day.Monday,输出结果就是Monday。可以覆写enum类型的toString()方法,改成自己期望的值,比如我们下边给出的示例toString()就打印了别的信息,不是常量名字本身。

7. enum类里边的静态常量不一定是该enum 类的对象,也可以是enum类的子类对象。比如下边代码中例子,每个static常量对象,都是一个重写了apply()抽象方法的子类对象。这样做的好处是防止以后添加新的常量时,没有添加该常量对应的动作。

下边的类似,参考了《effective java》中的一个例子,稍微有一点复杂。但是如果你能从类的角度去理解enum定义的类型,就很容易理解,而且enum定义的的确是类哦,只不过这个类里边有一些静态引用类型的常量,指向了一些类型本身的对象:

package enumeration;

public class EnumDemo2 {
	public static void main(String[] args) {
		double x = 10.36;
		double y = 2.37;
		//使用enum
		Operation[] values = Operation.values();
		for (Operation operation : values) {
			System.out.println("x " + operation + " y = " + operation.apply(x, y));
		}
		
		System.out.println("*****************");
		
		//使用自定义普通类代替enum
		Operator1[] values1 = Operator1.values();
		for (Operator1 operation : values1) {
			System.out.println("x " + operation + " y = " + operation.apply(x, y));
		}
	}

}

//enum类型
enum Operation {
    //这里,常量指向的是子类的对象,这里使用了类似于匿名类的方式来给这些常量赋值。
    //Operation PLUS = new Operation(){ 覆写的方法 ... }
	PLUS("+") {
		public double apply(double x, double y) {
			return x + y;
		}
	},
	
	MINUS("-") {
		public double apply(double x, double y) {
			return x - y;
		}
	},
	
	MULTIPLY("*"){
		public double apply(double x, double y) {
			return x * y;
		}
	},
	
	DEVIDE("/"){
		public double apply(double x, double y) {
			return x / y;
		}
	};

	private final String opertator;

	Operation(String operator) {
		this.opertator = operator;
	}

	public abstract double apply(double x, double y);
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return opertator;
	}
	

}
//自定义类,可以实现跟enum类的类似的功能。
abstract class Operator1 {
	public static final Operator1 PLUS = new Operator1("+") {
		public double apply(double x, double y) {
			return x + y;
		}
	};
	public static final Operator1 MINUS = new Operator1("-") {
		public double apply(double x, double y) {
			return x - y;
		}
	};
	public static final Operator1 MULTIPLY = new Operator1("*") {
		public double apply(double x, double y) {
			return x * y;
		}
	};
	public static final Operator1 DIVIDE = new Operator1("/") {
		public double apply(double x, double y) {
			return x / y;
		}
	};
	

	private final String opertator;

	Operator1(String operator) {
		this.opertator = operator;
	}

	public abstract double apply(double x, double y);
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return opertator;
	}
	
	public static Operator1 [] values() {
		Operator1 [] values = new Operator1[4];
		values[0] = PLUS;
		values[1] = MINUS;
		values[2] = MULTIPLY;
		values[3] = DIVIDE;
		
		return values;
	} 
	
}

output:
-----------
x + y = 12.73
x - y = 7.989999999999999
x * y = 24.5532
x / y = 4.371308016877637
*****************
x + y = 12.73
x - y = 7.989999999999999
x * y = 24.5532
x / y = 4.371308016877637

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值