`
joyocaowei
  • 浏览: 32775 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAVA枚举基础

 
阅读更多

枚举类型(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枚举类型说明

    下面是一些关于Java枚举的基础知识点: - **定义**: 使用`enum`关键字定义枚举类型,可以在枚举类型中定义一组固定的值,这些值都是该枚举类型的实例。 - **实例**: 枚举类型的每一个值都可以看作是该枚举类型的一...

    谈谈你可能并不了解的java枚举

    本文将深入探讨Java枚举的一些鲜为人知的特性。 1. 枚举默认值与自定义值: Java枚举的默认值是从0开始的整数序列,如示例中的Color枚举。然而,我们可以通过自定义构造函数为每个枚举实例赋予特定的值,如...

    Java 基础枚举.pdf

    Java 枚举是一种特殊的类,用于定义一组固定的常量,这些常量代表特定的值或状态。枚举在编程中非常有用,特别是在处理有限数量的选项时,如颜色、星期几、季节等。通过使用枚举,我们可以确保代码的健壮性,避免因...

    java枚举的一个例子

    ### Java枚举详解 在Java编程语言中,枚举(`enum`)是一种特殊的类,用于定义一组固定的常量值。这些常量值通常代表了一组预定义的选项或者状态,比如颜色、方向等。使用枚举可以提高代码的可读性和可维护性,并且...

    枚举java基础知识点

    枚举Java基础知识点 Java中的枚举(Enumeration)是一种特殊的数据类型,它可以将一组固定的常量分组到一个枚举类型中,使得代码更加简洁、易读和维护。枚举的用法非常广泛,在Java中有多种使用方式,我们将逐一...

    java枚举使用详细介绍及实现

    1. 枚举的基础知识 在 Java 中,枚举是一种特殊的类,它继承自 java.lang.Enum 类。枚举可以拥有构造器、方法和变量,枚举的实例是固定的,不能被修改。枚举的实例可以通过枚举名.值的方式来访问。 2. 枚举的使用...

    Java编程基础教程:枚举与泛型的深入讲解

    适用人群:适用于具有一定Java编程基础的学习者和开发者,特别推荐给希望深入了解Java核心技术的专业人士。 使用场景及目标:本文旨在提升读者对于Java中枚举和泛型的理解与应用能力,包括掌握如何高效地定义和使用...

    Java基础案例教程(第2版)-教学设计.zip

    《Java基础案例教程(第2版)》是一本旨在教授初学者Java编程基础知识的教材,其教学设计旨在通过实例引导学生深入理解Java语言的核心概念。本教程覆盖了从环境搭建到程序设计的各个环节,旨在帮助学生建立起坚实的...

    9.尚硅谷_java基础_枚举&注解

    枚举 定义 自实现枚举类 使用 enum 定义枚举类 实现接口的枚举类 枚举类的方法 注解

    大学课程讲义-Java基础-枚举&注解.pptx

    Java 基础知识点总览 - 枚举和注解 Java 中的枚举(enumeration)是一种特殊的数据类型,它可以表示有限的、固定的常量集。枚举类是一种特殊的类,它的对象是有限的、固定的和不可变的。 枚举的定义 在 Java 中,...

    java基础资料

    12. **枚举类型**:Java 5引入了枚举,用于定义一组固定的常量。 13. **泛型**:泛型允许在类、接口和方法中使用类型参数,增强了代码的类型安全性和重用性。 14. **Java SE (标准版)**:"老王java se"可能是指...

    java基础学习课件ppt

    Java基础学习课件PPT是一套全面覆盖Java SE(标准版)基础知识的教育资源,适合初学者和希望巩固Java技能的开发者。这套课件旨在在一个月内帮助学习者掌握Java编程的核心概念,为深入学习和应用Java技术打下坚实的...

    大学本科Java基础课件涵盖项目源代码课件PPT.zip

    Java基础 枚举&注解pptx Java基础泛型docx Java基础_网络编程pptx Java基础面向对象pptx Java基础_高级类特性.pptx Java基础实战Bank项目文档需求源代码 01 Java基础实战Bank项目文档需求源代码 02 Java基础实战Bank...

    Java基础教程PPT

    最后,可能会简要介绍Java的泛型、注解和枚举,这些都是现代Java编程中不可或缺的特性。 在学习过程中,PPT通常会包含实例代码和解释,帮助学习者更好地理解和应用这些概念。同时,课后练习和项目实践是巩固理论...

    Java 入门 基础 代码

    本资料包"Java 入门 基础 代码"提供了100个小型Java编程实例,旨在帮助初学者逐步理解并熟练运用Java的基本语法和概念。 首先,Java的基础入门通常包括以下几个方面: 1. **环境搭建**:学习Java的第一步是安装...

    Java枚举详解及使用实例(涵盖了所有典型用法)

    Java枚举是Java语言中的一种特殊类,它用于定义一组有限的、预定义的值。枚举在Java中扮演着重要的角色,尤其是在处理固定集合的数据时,如颜色、星期、季节等。下面将详细介绍Java枚举的使用及其各种典型用法。 1....

    java核心基础技术卷,(基础语法,面向对象,异常,泛型,IO,枚举,反射机制,集合,内部类,)

    "Java核心基础技术卷详解" ...Java 核心基础技术卷涉及到 Java 的基础语法、面向对象、异常、泛型、IO、枚举、反射机制、集合、内部类等多方面的知识点,为 Java 开发者提供了一个全面的学习指南。

    Java基础尚硅谷宋红康学习笔记

    3. **枚举**:枚举是Java中的一种特殊类,用于定义一组固定的常量,提高了代码的可读性和安全性。 4. **注解(Annotation)**:注解提供了一种元数据,用于向编译器或JVM提供关于代码的附加信息,例如用于代码生成...

    Java语言基础入门教程 Java实训教程 10.枚举与泛型 共27页.pptx

    ### Java语言基础入门教程知识点详解 #### 10. 枚举与泛型 ##### 10.1 枚举(Enum) **10.1.1 枚举定义** 枚举是一种特殊的类,用于定义那些取值范围固定且不会发生变化的数据类型。例如,性别、星期、月份等。 ...

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 05. 自定义枚举类.avi

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 05. 自定义枚举类.avi

Global site tag (gtag.js) - Google Analytics