Java枚举
Java 5.0引入了枚举类型,可以使用该功能取代以往定义常量的方法。枚举类型赋予程序在编译时检查的功能,可以减少代码中的bug。
1.枚举类型简介
如果我们想定义一个Color类,它只能有Red、Green、Blue三种值,其他值都是非法的,那么我们怎么做呢?
若我们使用类或接口来实现,可能要做很多工作或带来不安全因素。
但现在我们通过枚举类型(enum)就能简单实现以上功能了。
枚举就是规定好指定的取值范围,所有的内容只能从指定的范围中取代。实例如下:
public enum Color{
RED,GREEN,BLUE;//定义了三种颜色
}
public class GetColor{
publicstatic void main(String[] args){
Colorc=Color.RED; //取出红色
System.out.println(c);
}
}
2.使用枚举类型设置常量
在以往设置常量时,通常把常量放置在接口中,这样便可以通过“接口名.常量名”使用该常量了,但是该常量不能被修改(因为该常量的修饰符为final与static)。
在接口中定义常量如下:
public interface People{
public static final int MAX_AGE=150;
public static final int MIN_AGE=0;
}
现在,我们可以使用枚举来取代这种常量的定义方法了。
使用枚举定义常量如下:
public enum People{
MAX_AGE,
MIN_AGE
}
注:enum是定义枚举类型的关键字。
当在程序中需要使用枚举中的常量时,通过“枚举名.常量名”(如:Peple.MAX_AGE)来调用。(接口中定义的常量在调用时也是通过“接口名.常量名”)
枚举类型可以在类的内部进行定义,下面将介绍如何在类的内部定义枚举类型:
public class Student{
enum Age{ //将常量放到枚举类型中
MAX_AGE,
MIN_AGE
}
//主方法(程序入口)
public static void main(String[] args){
Student.checkAge(Age.MAX_AGE);
}
//使用枚举类型中的常量
public static void checkAge(Age a){
switch(a){
case MAX_AGE:
System.out.println("是最大年龄");break;
case MIN_AGE:
System.out.println("是最小年龄");break;
}
}
}
注:以上类似内部类的方法定义枚举,会在编译后生成“外部类名称$枚举名称.class文件”。
3.深入了解枚举类型
1.操作枚举类型成员的方法
我们可以把枚举类型看作是一个类,它继承自java.lang.Enum类,当定义一个枚举类型是,每一个枚举类型成员都可以看作是枚举类Enum的一个实例。
枚举类型的成员变量默认都被final、public、static所修饰,因此可以直接通过枚举类型名称调用枚举类型成员。
由于枚举类型对象继承自java.lang.Enum类,所以可以使用Enum类中的所有方法,下面列举一些常用方法:
方法名称 | 具体含义 | 使用方法 | 举例 |
values() | 将枚举类型成员以数组的形式返回 | 枚举类型名称.values() | People.values() |
valueOf() | 将普通字符串转化为枚举类型 | 枚举类型名称.valueOf(“abc”) | People.valueOf(“abc”) |
compareTo() | 比较两个枚举类型在定义时的顺序 | 枚举对象.compareTo() | MAX_AGE,compareTo(MIN_AGE) |
ordinal() | 得到枚举类型成员的位置索引 | 枚举对象.ordinal() | MAX_AGE.ordinal() |
1.values()方法
values()方法可以将枚举类型的成员变量实例以数组的形式返回,也可以通过该方法获取枚举类型的成员。
例如:
public class Student{
enum Age{ //将常量放到枚举类型中
MAX_AGE,
MIN_AGE
}
//main方法(程序入口)
public static void main(String[] args){
for(inti=0;i<Age.values().length;i++){
System.out.println("枚举类型成员变量:"+Age.values()[i]);
}
}
}
结果为:
枚举类型成员变量:MAX_AGE
枚举类型成员变量:MIN_AGE
2.valueOf()与compareTo()方法
valueOf()方法可以将普通字符串转换为枚举类型。
compareTo()方法可以用于比较两个枚举类型对象定义时的顺序。返回的结果若为正整数,代表方法中的参数在调用该方法的枚举对象位置之前;0代表两个互相比较的枚举成员的位置相同;负数代表方法中的参数在调用该方法的枚举对象的位置之后。
例如:
public class Student{
enum Age{ //将常量放到枚举类型中
MAX_AGE,
MIN_AGE
}
//main方法(程序入口)
public static void main(String[] args){
//调用compare()方法
compare(Age.valueOf("MIN_AGE"));
}
//定义比较枚举类型方法,参数类型为枚举类型
public static void compare(Age a){
//根据values()方法返回的数组做循环操作
for(inti=0;i<Age.values().length;i++){
System.out.println(a+"与"+Age.values()[i]+"的比较结果为:"+a.compareTo(Age.values()[i]));
}
}
}
结果为:
MIN_AGE与MAX_AGE的比较结果为:1
MIN_AGE与MIN_AGE的比较结果为:0
3.ordinal()方法
ordinal()方法可以用来获取某个枚举对象的位置索引值。
例如:
public class Student{
enum Age{ //将常量放到枚举类型中
MAX_AGE,
MIN_AGE
}
//main方法(程序入口)
public static void main(String[] args){
for(inti=0;i<Age.values().length;i++){
//在循环中获取枚举类型成员的索引位置
System.out.println(Age.values()[i]+”在枚举类型中位置索引值为:”+ Age.values()[i].ordinal());
}
}
}
结果为:
MAX_AGE在枚举类型中位置索引值为:0
MIN_AGE在枚举类型中位置索引值为:1
2.枚举类型中的构造方法
在枚举类型中,可以添加构造方法,但是规定这个构造方法必须是private修饰符所修饰。
枚举类型定义的构造方法语法如下:
enum 枚举类型名称{
Constants_A("我是枚举类型成员A"),
Constants_B("我是枚举类型成员B"),
Constants_C("我是枚举类型成员C"),
Constants_D(3);
//定义字符串变量
privateString description;
//定义整型变量
privateint i;
//定义默认构造方法
private 枚举类型名称(){
}
//定义带参数的构造方法,参数类型为字符串
private 枚举类型名称(String description){
this.description= description;
}
//定义带参数的构造方法,参数类型为整型
private 枚举类型名称(int i){
this.i= this.i+i;
}
}
从以上代码可以看出,无论是无参构造方法还是有参构造方法,修饰权限都为private。
当定义一个有参构造方法后,需要将枚举类型成员相应地使用该构造方法,如:Constants_A(“我是枚举类型成员A”)使用了参数为String型的构造方法;Constants_D(3)使用了参数为int型的构造方法。
然后在枚举类型中再定义两个成员变量,在构造方法中为成员变量赋值,这样就可以在枚举类型中定义该成员变量相应的getXXX()方法,以赋予枚举类型成员值,如:这里定义两个方法getDescription(){returndescription; }和getI(){returnI;}。
实例如下:
public class EnumTest{
enum Contstants{
Constants_A("我是枚举类型成员A"),
Constants_B("我是枚举类型成员B"),
Constants_C("我是枚举类型成员C"),
Constants_D(3);
//定义字符串变量
private String description;
//定义整型变量
private int i=4;
//定义默认构造方法
private Contstants(){
}
//定义带参数的构造方法,参数类型为字符串
private Contstants(String description){
this.description= description;
}
//定义带参数的构造方法,参数类型为整型
private Contstants(int i){
this. i= this.i+i;
}
public String getDescription(){
return description;
}
public int getI(){
return i;
}
}
public static void main(String[] args) {
for(inti=0;i<Constants.values().length;i++){
System.out.println(Constants.values()[i]+"调用getDescription()方法为:"+Constants.values()[i].getDescription());
}
System.out.println(Constants.valueOf("Constants_D")+"调用getI()方法为:"+Constants.valueOf("Constants_D").getI());
}
}
结果为:
Constants_A调用getDescription()方法为:我是枚举类型成员A
Constants_B调用getDescription()方法为:我是枚举类型成员B
Constants_C调用getDescription()方法为:我是枚举类型成员C
Constants_D调用getDescription()方法为:null
Constants_D调用getI()方法为:7
上面的实例中,我们通过定义getDescription()方法获取枚举类型成员定义时的描述,除此之外,我们还可以将getDescription()方法放置到接口中,使枚举实现该接口,然后每个枚举类型实现接口中的方法。
实例如下:
interface IEnum
{
public String getDescription();
public int getI();
}
public enum AnyEnum implements IEnum{
Constants_A{//可以在枚举类型成员内部设置方法
publicString getDescription(){
return"我是枚举成员A";
}
publicint getI(){
returni;
}
},
Constants_B{//可以在枚举类型成员内部设置方法
publicString getDescription(){
return"我是枚举成员B";
}
publicint getI(){
returni;
}
},
Constants_C{//可以在枚举类型成员内部设置方法
publicString getDescription(){
return"我是枚举成员C";
}
publicint getI(){
returni;
}
},
Constants_D{//可以在枚举类型成员内部设置方法
publicString getDescription(){
return"我是枚举成员D";
}
publicint getI(){
returni;
}
};
private static int i=5;
public static void main(String[] args){
for(int j=0;j<AnyEnum.values().length;j++){
System.out.println(AnyEnum.values()[j]+"调用getDescription()方法为:"+ AnyEnum.values()[j].getDescription());
System.out.println(AnyEnum.values()[j]+"调用getI()方法为:"+ AnyEnum.values()[j].getI());
}
}
}
结果为:
Constants_A调用getDescription()方法为:我是枚举成员A
Constants_A调用getI()方法为:5
Constants_B调用getDescription()方法为:我是枚举成员B
Constants_B调用getI()方法为:5
Constants_C调用getDescription()方法为:我是枚举成员C
Constants_C调用getI()方法为:5
Constants_D调用getDescription()方法为:我是枚举成员D
Constants_D调用getI()方法为:5