- 浏览: 484624 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
TrueBrian 写道有个问题,Sample 1中,为了控制 ...
What's New on Java 7 Phaser -
龘龘龘:
楼主总结的不错。
What's New on Java 7 Phaser -
TrueBrian:
有个问题,Sample 1中,为了控制线程的启动时机,博主实际 ...
What's New on Java 7 Phaser -
liguanqun811:
不知道楼主是否对zookeeper实现的分布式锁进行过性能测试 ...
Distributed Lock -
hobitton:
mysql的get lock有版本限制,否则get lock可 ...
Distributed Lock
1 Introduction to enum
Java SE 5中引入了枚举,同时添加了一个新关键字enum。下面是个枚举的例子:
public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES; }
枚举类型也是普通的Java类,继承自java.lang.Enum并默认实现了java.lang.Comparable接口和java.io.Serializable接口。所有的枚举类型都是final类,枚举值都是public static final,由于枚举值是常量,因此枚举值的名称通常应该大写。
枚举类型也可以声明构造函数(只能是私有或者包级私有)、成员变量和成员方法,此外也能实现接口。需要注意的是,成员变量和成员方法的声明必须放在所有枚举值定义的后面,例如:
public enum Status { // Normal("normal"), Warning("warning"), Error("error"), Fatal("fatal"); // private String description; private Status(String description) { this.description = description; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
Enum声明了name()方法和oridinal()方法,分别用于返回枚举值的名称和该枚举值在枚举类型中声明的顺序(从0开始),例如NORMAL.ordinal()返回0。Enum改写了toString方法,返回枚举值的名称。下面是个简单的例子:
public static void main(String args[]) { // System.out.println("super class: " + Status.class.getSuperclass()); // System.out.println(Status.valueOf("Normal").getDescription()); // for(Status s: Status.values()) { System.out.println(s + ":" + s.ordinal()); } // Status status = Status.Normal; switch(status) { case Normal: System.out.println("Status.Normal"); break; case Warning: System.out.println("Status.Warning"); break; case Error: System.out.println("Status.Error"); break; case Fatal: System.out.println("Status.Fatal"); break; default: System.out.println("unknown"); break; } // EnumMap<Status, String> map = new EnumMap<Status, String>(Status.class); map.put(Status.Normal, "normal status"); map.put(Status.Warning, "warning status"); map.put(Status.Error, "error status"); map.put(Status.Fatal, "fatal status"); // EnumSet<Status> set = EnumSet.of(Status.Normal, Status.Warning); for(Status s : set) { System.out.println(s); } }
以上程序的输出如下。需要注意的是,case语句只需将其写成 case Normal 即可,也就是说不必写成 case Status.Normal,实际上如果写成Status.Normal,那么会导致编译错误。
super class: class java.lang.Enum normal Normal:0 Warning:1 Error:2 Fatal:3 Status.Normal Normal Warning
2 Inside java.lang.Enum
2.1 Instantiation
首先java.lang.Enum类的签名如下,其中<E extends Enum<E>>是递归类型限制,主要目的是提供compareTo(E e) 而不是compareTo(Enum e)。
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
java.lang.Enum中唯一的构造函数如下,所有的成员变量都在构造函数内初始化。由于所有的成员变量都是不可变类型或者基本类型,因此没有额外的保护性拷贝。构造之后,所有的成员变量便处于只读状态。需要注意的是,java.lang.Enum的子类不一定是不可变类(虽然通常应该是不可变类),因为程序中定义的枚举类型可以包含可变的成员变量。
protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; }
java.lang.Enum类提供了一个静态工具方法,用于获得某个枚举类型中,名为name的枚举值。该方法通过调用java.lang.Class的 enumConstantDirectory()方法获得该枚举类型所有枚举值的map。java.lang.Class的enumConstantDirectory()方法内又通过反射调用了该枚举类型的values()方法获得所有的枚举值。需要注意的是,java.lang.Enum中并没有一个名为values()的静态方法,这个方法是编译器在编译枚举类型时添加的。
public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) { T result = enumType.enumConstantDirectory().get(name); if (result != null) return result; if (name == null) throw new NullPointerException("Name is null"); throw new IllegalArgumentException("No enum const " + enumType +"." + name); }
2.2 Equality
public final boolean equals(Object other) { return this==other; } public final int hashCode() { return super.hashCode(); }
从以上代码中可以看出,对于枚举值的相等性判断,只需要判断引用是否相等即可。需要注意的是,这是在充分考虑了反射、对象克隆和序列化等诸多因素之后作出的决定。
java.lang.reflect.Constructor的newInstance()方法中有如下代码,禁止了通过反射构造枚举对象:
if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects");
2.3 Comparison
以下是跟枚举比较相关的代码:
public final Class<E> getDeclaringClass() { Class clazz = getClass(); Class zuper = clazz.getSuperclass(); return (zuper == Enum.class) ? clazz : zuper; } public final int compareTo(E o) { Enum other = (Enum)o; Enum self = this; if (self.getClass() != other.getClass() && // optimization self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal; }
假设程序中定义的所有枚举类型都是继承自java.lang.Enum,而且所有的枚举类型都被声明为final类,这是否意味着所有枚举值的super class都应该是java.lang.Enum?为什么在getDeclaringClass()方法内会有对super class的判断呢?分析以下例子:
public enum Operation { PLUS { double eval(double x, double y) { return x + y; } }, MINUS { double eval(double x, double y) { return x - y; } }, TIMES { double eval(double x, double y) { return x * y; } }, DIVIDE { double eval(double x, double y) { return x / y; } }; abstract double eval(double x, double y); public static void main(String args[]) { System.out.println(Operation.TIMES.getClass()); System.out.println(Operation.TIMES.getClass().getSuperclass()); System.out.println(Operation.TIMES.getDeclaringClass()); } }
以上程序的输出如下:
class Operation$3 class Operation class Operation
从这个例子可以看出,并不是所有的枚举值的super class都是Emum.class。在compareTo()方法内需要判断getDeclaringClass()和ordinal是否相等。就像其注释中说明的那样,判断getClass()是否相等只是一种优化。
此外,java.lang.Class类中包含以下代码,用于判断一个类是否是枚举类型。需要注意的是,这里没有使用getDeclaringClass(),而是直接使用getSuperclass()进行判断。
public boolean isEnum() { // An enum must both directly extend java.lang.Enum and have // the ENUM bit set; classes for specialized enum constants // don't do the former. return (this.getModifiers() & ENUM) != 0 && this.getSuperclass() == java.lang.Enum.class; }
2.4 Clone
以下是java.lang.Enum类的clone()方法,该方法中直接抛出CloneNotSupportedException异常,这保证了java.lang.Enum无法被克隆,从而保证了枚举值的单例性(通常情况下,只有一个继承链上的除了java.lang.Object之外的所有类都在clone()方法内返回通过调用super.clone()方法返回的对象,那么才能保证clone的正确性)。
protected final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
2.5 Serialization
java.lang.Enum类中序列化相关的代码如下:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum"); } private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum"); }
java.lang.Enum类实现了Serializable接口,但是却在readObject()和readObjectNoData()方法内直接抛出异常(如果某个类因为继承的原因实现了Serializable接口,而该类却不希望被序列化/反序列化,那么通常可以考虑在readObject()和writeObject()方法中直接抛出异常)。
实际上,Java的序列化机制对于枚举类型有特殊的处理,即没有使用普通对象的序列化形式:尽管java.lang.Enum中的name和ordial成员变量都没有声明为transient,实际上序列化过程中写入流的只有name;反序列化过程中通过调用Enum.valueOf(Class<T> enumType, String name)静态方法构造枚举值,从而保证了枚举值的单例性。
评论
升级到JDK1.5后.和enum关键字产生冲突.代码大面积红叉....
enumClass.get("XXX").get(null);
发表评论
-
Understanding the Hash Array Mapped Trie
2012-03-30 10:36 0mark -
A Hierarchical CLH Queue Lock
2012-01-14 19:01 2152A Hierarchical CLH Queue Lock ( ... -
Inside AbstractQueuedSynchronizer (4)
2012-01-08 17:06 3529Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (3)
2012-01-07 23:37 4757Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (2)
2012-01-07 17:54 6377Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (1)
2012-01-06 11:04 7953Inside AbstractQueuedSynchroniz ... -
Code Optimization
2011-10-14 00:11 1613当前开发人员在进行编码的时候,可能很少关注纯粹代码级别的优化了 ... -
Distributed Lock
2011-08-02 22:02 92191 Overview 在分布式系统中,通常会 ... -
What's New on Java 7 Phaser
2011-07-29 10:15 82921 Overview Java 7的并 ... -
Sequantial Lock in Java
2011-06-07 17:00 22251 Overview Linux内核中常见的同步机 ... -
Feature or issue?
2011-04-26 22:23 121以下代码中,为何CglibTest.intercept ... -
Bloom Filter
2010-10-19 00:41 50811 Overview Bloom filt ... -
Open Addressing
2010-07-07 17:59 34841 Overview Open addressi ... -
JLine
2010-06-17 09:11 11015Overview JLine 是一个用来处理控 ... -
ID Generator
2010-06-14 14:45 1686关于ID Generator,想 ... -
inotify-java
2009-07-22 22:58 83171 Overview 最近公 ... -
Perf4J
2009-06-11 23:13 84941 Overview Perf4j是一个用于计算 ... -
Progress Estimator
2009-02-22 19:37 1542Jakarta Commons Cookbook这本书 ... -
jManage
2008-12-22 00:40 39611 Overview 由于项目需要, 笔者开发了一个 ... -
JMX Remoting
2008-09-24 10:29 60821 Introduction Java Manage ...
相关推荐
org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons...
org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons...
在比较字符串与文字时,如果文字可以是一个字符串或Enum的元素,也可能会抛出java.lang.NullPointerException异常。例如: String str = null; if (str.equals("Test")) { // 这里将抛出java.lang....
Java 5引入的枚举类型(如`java.lang.enum`)提供了一种安全的常量表示方式。 7. **System.in/err/out**:`System`类的静态变量`in`、`err`和`out`分别代表标准输入、错误输出和标准输出流,它们在I/O编程中扮演着...
org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons....
在 Java 中,枚举类型可以使用 enum 关键字来定义。 在 Spring Boot 应用程序中,枚举类型经常被用于定义一些固定的值,例如订单状态、用户角色等。然而,在使用枚举类型时,需要注意一些坑,否则可能会出现一些...
- `BIGINT`: 用来存储大整数,对应 Oracle 的 `NUMBER(19,0)`,Java 中可使用 `java.lang.Long` 对应。 - `BIT`: 存储位数据,Oracle 没有直接对应的数据类型,通常使用 `RAW` 类似。 - `BLOB`: 用于存储大对象,...
7. **枚举和注解**:Java 5引入了枚举和注解,API文档中也有详细的描述,例如`java.lang.Enum`是所有枚举类型的基类,`java.lang.annotation`包提供了注解的相关类。 8. **多线程**:Java提供了丰富的多线程支持,`...
12. **枚举(Enum)**: `java.lang.Enum`提供了枚举类型的支持,枚举常量可以拥有方法和属性,使得常量集合更易于管理。 通过深入学习这份中文API文档,你可以全面掌握Java平台的核心功能,无论你是初学者还是有...
"JAVA-API.zip"的压缩包可能还包含了其他高级特性的文档,如反射(java.lang.reflect)、注解(java.lang.annotation)、泛型(generics)、枚举(enum)以及Lambda表达式等。这些内容是Java 5及以后版本引入的,极...
4. **枚举(Enum)**:Java允许定义枚举类型,这是一种特殊的类,可以有预定义的实例。比如`java.util.concurrent.TimeUnit`枚举用于表示时间单位。 5. **异常(Exception)**:Java通过异常处理来处理程序运行时...
其中的lang.enum已不建议使用,替代它的是紧随其后的lang.enums包。 lang包主要是一些可以高度重用的Util类;lang.builder包包含了一组用于产生每个Java类中都常使用到的toString()、 hashCode()、equals()、...
5. **枚举和注解**:Java 5引入了枚举和注解,这些在API文档中也有详尽的解释,如`java.lang.annotation`包下的注解类型,以及`java.lang.Enum`作为所有枚举类型的基类。 6. **附录**:通常包括一些补充信息,如...
11. EnumSet和EnumMap:针对枚举类型(enum)的高效集合实现,优化了枚举操作。 12. WeakHashMap:键使用弱引用的Map,当键不再被引用时,条目会自动从Map中移除。 13. Timer和TimerTask:定时任务调度,可以安排...
8. **枚举和注解**:Java 5引入了枚举和注解,API文档也对这些新特性进行了详细解释,如`java.lang.Enum`作为所有枚举类型的基类,`java.lang.annotation`包下的注解接口。 9. **并发编程支持**:Java API提供了...
10. **枚举(Enum)**:Java 5引入的枚举类型是常量的集合,可以避免使用传统的整数常量来表示一组固定的值,增强了代码的可读性和安全性。 学习和理解Java API中文文档对于Java开发者至关重要,它不仅提供了对API...
1. **基础包**:`java.lang`是最基础的包,包括了所有Java程序都会自动导入的基本类,如`Object`(所有类的父类)、`String`(字符串类)、`System`(系统相关操作)以及异常处理类`Exception`等。 2. **集合框架**...
枚举在Java中被设计为一种特殊的类,它们默认继承自`java.lang.Enum`抽象类,并且是单继承的,这意味着它们无法再继承其他类,但可以实现多个接口。下面我们将深入探讨enum的使用方法、特性以及常见的操作。 1. **...
枚举默认继承`java.lang.Enum`类,因此它们不能直接继承其他类,但可以实现接口。这使得枚举可以具有特定的行为。 6. **枚举常量的遍历** 可以通过for-each循环遍历枚举的所有实例,如: ```java for (Color ...
5. **枚举和注解**:Java 5引入了枚举和注解,这些在API文档中也有详细介绍,例如`java.lang.Enum`表示枚举类型,`java.lang.annotation.Annotation`是注解的基类。 6. **异常处理**:Java API文档也涵盖了所有的...