我们之前学习了各种数据类型,比如int类型,只要是在应该特定范围内的整数,都可以储存在int类中。有时候,我们需要创造属于自己的数据类型并限定范围,比如我们可以创建一种有一周七天的数据类型Day,里面包含周一,周二,周三等等。Day类型里只会有七个合法的值,这种类型在java中被称为枚举类(enumerated data type)。
我们可以使用关键字enum来创建枚举类,并+设定枚举类中合法的值。
enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY }
一个枚举类型的声明以关键字enum开始,接着是这个类型的名字(Day),然后是储存在大括号里的枚举类的内容。注意到枚举类中的内容没有引号,所以这里的SUNDAY,MONDAY等等并不是string。并且枚举类中的内容必须是合法的java的识别符。
枚举类中的内容并不一定要大写,但是在枚举类中大写是一种良好的编程习惯。
在声明完枚举类之后,就可以声明枚举类的变量并进行赋值了。
声明:
Day workDay;
赋值:
Day workDay = Day.WEDNESDAY;
workday是一个Day类型的变量,所以它只有七合法的个值。并且注意在赋值的时候没有直接写Wednesday,而是写day.Wednesday,要使用完全限定名(fully qualified name)。
为什么要这样呢?
实际上当我们在对枚举类赋值的时候,我们是在创建一种特殊类型的类。也就是说枚举类括号中内容并不单单只是对这个枚举类各合法值的“声明”,而是对一个枚举类对象的声明。(不是告诉编译器这些值是合法的,而是直接声明了一个Day类的对象)比如Sunday就是一个对Day类中一个叫Sunday的对象的声明。当我们将Day.WEDNESDAY赋值给workDay时,实际上是将Day.WEDNESDAY object的地址赋值给这个变量。
之前我们提到一个枚举类的值实际上是一个对象,当我们打印一个值的时候,比如int 1,会直接打印1,但是当我们打印一个对象的时候,会直接打印地址。但是如果这个对象有toString方法,那么就会根据toString方法打印相应的内容。枚举类的toString方法默认打印的就是对象的内容,比如day.Wednesday就会打印Wednesday。
// This code displays WEDNESDAY.
Day workDay = Day.WEDNESDAY;
System.out.println(workDay);
// This code also displays WEDNESDAY.
System.out.println(Day.WEDNESDAY);
ordinal方法返回一个表示该枚举类元素的序数的整数,枚举类的第一个元素的序数为0.
Day lastWorkDay = Day.FRIDAY;
System.out.println(lastWorkDay.ordinal());
System.out.println(Day.MONDAY.ordinal());
输出如下:
51
该方法被设计用于比较相同类的枚举值。它接受一个对象,如果调用枚举常数的顺序值小于参数的顺序值就返回一个负整数值;如果调用枚举常数是相同的参数就返回零;如果调用枚举常数的顺序值大于参数的顺序值就返回一个正整数值。
/**
This program demonstrates an enumerated type.
*/
public class EnumDemo
{
// Declare the Day enumerated type.
enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
public static void main(String[] args)
{
// Declare a Day variable and assign it a value.
Day workDay = Day.WEDNESDAY;
// The following statement displays WEDNESDAY.
System.out.println(workDay);
// The following statement displays the ordinal
// value for Day.SUNDAY, which is 0.
System.out.println("The ordinal value for " +
Day.SUNDAY + " is " +
Day.SUNDAY.ordinal());
// The following statement displays the ordinal
// value for Day.SATURDAY, which is 6.
System.out.println("The ordinal value for " +
Day.SATURDAY + " is " +
Day.SATURDAY.ordinal());
// The following statement compares two enum constants.
if (Day.FRIDAY.compareTo(Day.MONDAY) > 0)
System.out.println(Day.FRIDAY + " is greater than " +
Day.MONDAY);
else
System.out.println(Day.FRIDAY + " is NOT greater than " +
Day.MONDAY);
}
}
WEDNESDAYThe ordinal value for SUNDAY is 0The ordinal value for SATURDAY is 6FRIDAY is greater than MONDAY
之前我们在的枚举类都是在某一个类中的,比如枚举类Day是写在EnumDemo类中的,就像一个内部类一样,当然我们也可以单独写一个枚举类。
/**
CarType enumerated data type
*/
enum CarType { PORSCHE, FERRARI, JAGUAR }
这就是一个完整的枚举类了。
下面看demo程序:
/**
This program shows that you can switch on an
enumerated type.
*/
public class SportsCarDemo2
{
public static void main(String[] args)
{
// Create a SportsCar object.
SportsCar yourNewCar = new SportsCar(CarType.PORSCHE,
CarColor.RED, 100000);
// Get the car make and switch on it.
switch (yourNewCar.getMake())
{
case PORSCHE :
System.out.println("Your car was made in Germany.");
break;
case FERRARI :
System.out.println("Your car was made in Italy.");
break;
case JAGUAR :
System.out.println("Your car was made in England.");
break;
default:
System.out.println("I'm not sure where that car "
+ "was made.");
}
}
}
注意这里的yourNewCar.getMake()方法,这里的case语句用的不是完全限定名(fully qualified name),而是只有枚举类的值,因为这里的枚举类不是写在别的类里面的,如果在这种情况下使用完全限定名,编译器会报错。