枚举类型(enum type)是指由一组固定的常量组成合法值的类型,例如一年中的季节、太阳系中的行星或者一副牌中的花色。
(An enumerated type is a type whose legal values consist of a fixed set of constants,such as the seasons of the year, the planets in the solar system, or the suits in a deck of playing cards.
)
Java的枚举本质上是int值,它的基本想法是: 通过公有的静态的final域为每个枚举常量导出实例的类。
(they are classes that export one instance for each enumeration constant via a public static final field.
)
也就是说它的每个枚举的实例类修饰符为public static final
由于枚举都继承自java.lang.Enum类,而java不支持多继承,但是可以实现一个或者多个接口。对于enum而言,实现接口是其子类化的唯一方法
,可以看个例子:
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}
下面的程序说明所以东西都是某种类型的Food:
import static Food.*;
public class TypeOfFood {
public static void main(String[] args) {
Food food = Appetizer.SALAD;
food = MainCourse.LASAGNE;
food = Dessert.GELATO;
food = Coffee.CAPPUCCINO;
}
}
事实上看反编译的字节码也能看出一些东西,我使用的方便易工具是JDK(1.6)自带的javap工具,关于它的一些基本使用,可以参考文档:http://docs.oracle.com/javase/6/docs/technotes/tools/windows/javap.html
Planet类(下面的具体实例)字节码反编译的部分代码:
public final class test.effective.chapter6.Planet extends java.lang.Enum{
public static final test.effective.chapter6.Planet MERCURY;
public static final test.effective.chapter6.Planet VENUS;
public static final test.effective.chapter6.Planet EARTH;
public static final test.effective.chapter6.Planet MARS;
public static final test.effective.chapter6.Planet JUPITER;
public static final test.effective.chapter6.Planet SATURN;
public static final test.effective.chapter6.Planet URANUS;
public static final test.effective.chapter6.Planet NEPTUNE;
一个具体的实例:
// Enum type with data and behavior
public enum Planet {
MERCURY(3.302e+23, 2.439e6), VENUS(4.869e+24, 6.052e6), EARTH(5.975e+24,
6.378e6), MARS(6.419e+23, 3.393e6), JUPITER(1.899e+27, 7.149e7), SATURN(
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,构造器只能是私有的private
// 这样可以保证外部代码无法新构造枚举类的实例。
// 这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。
private 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
}
// 根据某一物体在地球上的重量(175),显示出该物体在所有八颗行星上的重量。
public static void main(String[] args) {
double earthWeight = Double.parseDouble("175");
double mass = earthWeight / Planet.EARTH.surfaceGravity();
// Planet.values(),按照枚举的声明顺序返回它的值数组(returns an array of its values in
// the order they were declared)
for (Planet p : values())
// s表示字符串,f表示浮点数,n表示与平台无关的换行符
System.out.printf("Weight on %s is %f%n", p, p.surfaceWeight(mass));
}
}
刚开始看这个例子的时候,不知道values()方法是如何来的,后来看了一下(JLS8.9
),感觉有点明白了,它里面有这么一段解释:
In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods:
/**
* Returns an array containing the constants of this enum
* type, in the order they're declared. This method may be
* used to iterate over the constants as follows:
*
* for(E c : E.values())
* System.out.println(c);
*
* @return an array containing the constants of this enum
* type, in the order they're declared
*/
public static E[] values();
/**
* Returns the enum constant of this type with the specified
* name.
* The string must match exactly an identifier used to declare
* an enum constant in this type. (Extraneous whitespace
* characters are not permitted.)
*
* @return the enum constant with the specified name
* @throws IllegalArgumentException if this enum type has no
* constant with the specified name
*/
public static E valueOf(String name);
也就是说,这两个静态方法[ values() & valueOf(String name) ]是“隐藏”的,事实上这两个方法是由编译器添加的static方法。
我用JDK自带的javap工具生成的部分代码是这样的(cd到字节码所在的目录,使用命令javap -c Planet
):
public static test.effective.chapter6.Planet[] values();
Code:
0: getstatic #87; //Field ENUM$VALUES:[Ltest/effective/chapter6/Plane
t;
3: dup
4: astore_0
5: iconst_0
6: aload_0
7: arraylength
8: dup
9: istore_1
10: anewarray #1; //class test/effective/chapter6/Planet
13: dup
14: astore_2
15: iconst_0
16: iload_1
17: invokestatic #149; //Method java/lang/System.arraycopy:(Ljava/lang/Ob
ject;ILjava/lang/Object;II)V
20: aload_2
21: areturn
关于这些指令的大致意思,可以参考下面的这篇文章:Java二进制指令代码解析
。当然,最好的方法是查看java虚拟机规范,可以去这个网址
下载java se7的规范中文版。在最后,作者加入了这些指令的含义。
实例二:
如果多个枚举常量同时共享相同的行为,可以考虑策略枚举(Strategy enum)【from efective java 2】。
// The strategy enum pattern
public 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);
}
}
public static void main(String[] args) {
PayrollDay payroll = PayrollDay.MONDAY;
System.out.println(payroll.pay(8, 20));
}
}
参考资料:
effective java second edition item30
JLS8.9
core java 卷一
Thinking in java(4th)
分享到:
相关推荐
下面是一些关于Java枚举的基础知识点: - **定义**: 使用`enum`关键字定义枚举类型,可以在枚举类型中定义一组固定的值,这些值都是该枚举类型的实例。 - **实例**: 枚举类型的每一个值都可以看作是该枚举类型的一...
本文将深入探讨Java枚举的一些鲜为人知的特性。 1. 枚举默认值与自定义值: Java枚举的默认值是从0开始的整数序列,如示例中的Color枚举。然而,我们可以通过自定义构造函数为每个枚举实例赋予特定的值,如...
Java 枚举是一种特殊的类,用于定义一组固定的常量,这些常量代表特定的值或状态。枚举在编程中非常有用,特别是在处理有限数量的选项时,如颜色、星期几、季节等。通过使用枚举,我们可以确保代码的健壮性,避免因...
### Java枚举详解 在Java编程语言中,枚举(`enum`)是一种特殊的类,用于定义一组固定的常量值。这些常量值通常代表了一组预定义的选项或者状态,比如颜色、方向等。使用枚举可以提高代码的可读性和可维护性,并且...
枚举Java基础知识点 Java中的枚举(Enumeration)是一种特殊的数据类型,它可以将一组固定的常量分组到一个枚举类型中,使得代码更加简洁、易读和维护。枚举的用法非常广泛,在Java中有多种使用方式,我们将逐一...
1. 枚举的基础知识 在 Java 中,枚举是一种特殊的类,它继承自 java.lang.Enum 类。枚举可以拥有构造器、方法和变量,枚举的实例是固定的,不能被修改。枚举的实例可以通过枚举名.值的方式来访问。 2. 枚举的使用...
适用人群:适用于具有一定Java编程基础的学习者和开发者,特别推荐给希望深入了解Java核心技术的专业人士。 使用场景及目标:本文旨在提升读者对于Java中枚举和泛型的理解与应用能力,包括掌握如何高效地定义和使用...
《Java基础案例教程(第2版)》是一本旨在教授初学者Java编程基础知识的教材,其教学设计旨在通过实例引导学生深入理解Java语言的核心概念。本教程覆盖了从环境搭建到程序设计的各个环节,旨在帮助学生建立起坚实的...
枚举 定义 自实现枚举类 使用 enum 定义枚举类 实现接口的枚举类 枚举类的方法 注解
Java 基础知识点总览 - 枚举和注解 Java 中的枚举(enumeration)是一种特殊的数据类型,它可以表示有限的、固定的常量集。枚举类是一种特殊的类,它的对象是有限的、固定的和不可变的。 枚举的定义 在 Java 中,...
12. **枚举类型**:Java 5引入了枚举,用于定义一组固定的常量。 13. **泛型**:泛型允许在类、接口和方法中使用类型参数,增强了代码的类型安全性和重用性。 14. **Java SE (标准版)**:"老王java se"可能是指...
Java基础学习课件PPT是一套全面覆盖Java SE(标准版)基础知识的教育资源,适合初学者和希望巩固Java技能的开发者。这套课件旨在在一个月内帮助学习者掌握Java编程的核心概念,为深入学习和应用Java技术打下坚实的...
Java基础 枚举&注解pptx Java基础泛型docx Java基础_网络编程pptx Java基础面向对象pptx Java基础_高级类特性.pptx Java基础实战Bank项目文档需求源代码 01 Java基础实战Bank项目文档需求源代码 02 Java基础实战Bank...
最后,可能会简要介绍Java的泛型、注解和枚举,这些都是现代Java编程中不可或缺的特性。 在学习过程中,PPT通常会包含实例代码和解释,帮助学习者更好地理解和应用这些概念。同时,课后练习和项目实践是巩固理论...
本资料包"Java 入门 基础 代码"提供了100个小型Java编程实例,旨在帮助初学者逐步理解并熟练运用Java的基本语法和概念。 首先,Java的基础入门通常包括以下几个方面: 1. **环境搭建**:学习Java的第一步是安装...
Java枚举是Java语言中的一种特殊类,它用于定义一组有限的、预定义的值。枚举在Java中扮演着重要的角色,尤其是在处理固定集合的数据时,如颜色、星期、季节等。下面将详细介绍Java枚举的使用及其各种典型用法。 1....
"Java核心基础技术卷详解" ...Java 核心基础技术卷涉及到 Java 的基础语法、面向对象、异常、泛型、IO、枚举、反射机制、集合、内部类等多方面的知识点,为 Java 开发者提供了一个全面的学习指南。
3. **枚举**:枚举是Java中的一种特殊类,用于定义一组固定的常量,提高了代码的可读性和安全性。 4. **注解(Annotation)**:注解提供了一种元数据,用于向编译器或JVM提供关于代码的附加信息,例如用于代码生成...
### Java语言基础入门教程知识点详解 #### 10. 枚举与泛型 ##### 10.1 枚举(Enum) **10.1.1 枚举定义** 枚举是一种特殊的类,用于定义那些取值范围固定且不会发生变化的数据类型。例如,性别、星期、月份等。 ...
计算机后端-Java-Java核心基础-第23章 枚举类与注解 05. 自定义枚举类.avi