- 浏览: 485361 次
- 性别:
- 来自: OnePiece
文章分类
- 全部博客 (196)
- --------- 基础----------- (0)
- java 碎碎念 (12)
- java 并行编程 (11)
- java I/O (6)
- java Charset & Encoding (2)
- spring学习笔记 (8)
- 正则表达式 (5)
- web前端-javascript (11)
- web前端-jQuery (7)
- web前端-碎碎念 (1)
- mybatis (0)
- 数据库-通用 (8)
- 数据库-oracle (20)
- nosql-redis (11)
- nosql-mongoDB (1)
- xml (2)
- log4j (2)
- uml (3)
- web services: soap/wsdl (6)
- soa-tuscany (2)
- linux (6)
- ----------修养----------- (0)
- 深入理解java虚拟机 (7)
- java 设计模式 (9)
- 数据结构和算法 (2)
- 读书笔记--代码整洁之道 (2)
- 计算机基础 (1)
- -----------践行---------- (0)
- 重构(refactor) (7)
- jvm-诊断 (4)
- 数据库-让oracle跑得更快 (7)
- Nginx (6)
- ehcache (2)
- 短信开发 (1)
- Servlet+Filter+Listener (2)
- 运维 (6)
- 问题记录 (38)
- 杂七杂八 (12)
最新评论
-
zhanggang807:
第二种方法比较好
<spring> 定时任务每次都执行两次的问题,慎用new ClassPathXmlApplicationContext() -
assasszt:
谢谢分享,很清楚的讲明了原理。
字符集与字符编码简介 -
su0nils000:
难得的笔记
<进阶-2> 打造高效正则表达式 -
足至迹留:
mini188 写道用MD5来解决碰撞是不是也是可行的呢?个人 ...
Hash简介 -
mini188:
用MD5来解决碰撞是不是也是可行的呢?
Hash简介
参考:《java入门经典》《java核心技术 卷1》网络
1.枚举引入
通常需要一些只能从预定义的固定集合中取值的变量。例如,假设想要定义一个名为weekday的整型变量,用来存储表示星期几的整数值。该变量最好能限制在7个可能的值之内,每个值逐个对应星期一到星期日。这种情形下一种称作枚举类型(enumerated type),甚至简单地称作枚举(enumeration)的工具是自然的选择。可以使用如下声明语句为这种情况定义一个枚举:
enum Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
这里定义了一个新的类型Day,变量只能存储在括号中设定的其中一个值。名称Monday、
Tuesday 一直到Sunday 都称为枚举常量,而且它们标识了Day 类型的变量中仅允许的值。事实上,这些名称会对应到整数值,默认情况下从0 开始,但是它们与整型变量不同,因为它们只在枚举Day的上下文中存在。
注意:在Day 枚举定义的最后没有分号(如果枚举中还定义了其他成员,则必须有分号)。因为这里是定义一个类型,所以在反括号的后面不需要
添加分号。类型名Day 的开头使用一个大写的D,因为按照约定,定义的类型都以大写字母开头。
枚举常量的名称通常用全大写命名,对应了普通public final static常量的规则。
有了这个新类型,现在可以按照如下方式定义变量weekday:
Day weekday = Day.Tuesday;
这里声明了Day 类型的变量weekday 并且将其初始化为Tuesday。注意提供weekday 初始值的
枚举常量必须用枚举类型名限定(switch语句中的case后面使用枚举常量时不需要用枚举类型限定)。如果不要限定名,编译器就无法认出该常量。
枚举通常能包含所需要数目的枚举常量。这里是一个表示每年月份的枚举类型:
enum Month { January, February, March , April , May , June,
July , August , September, October, November, December }
可以按如下方式定义这种类型的变量:
Month current = Month.September; // Initialize to September
如果之后想要修改变量中存储的值,可以将其设置为一个不同的枚举常量:
current = Month.October;
current 变量现在包含枚举常量值October。
2.枚举使用
枚举类型其实是一种特殊形式的类,声明enum时不能继承一个超类,默认所有的枚举都自动地继承java.lang.Enum。在代码中定义枚举类型时,设定的枚举常量以一个类的实例被创建,这个类以java.lang包中的Enum类作为超类,所以跟类一样,在类的定义中可以放置枚举类型的定义,也可以将枚举类型定义放在一个单独的源文件中。
每个枚举常量对应的对象将常量的名称存储在一个域中,而枚举类类型从Enum类中继承toString()方法。Enum类中的toString()方法返回 枚举常量的原始名称,所以使用println()方法输出枚举常量时会获得枚举常量的名称。
表示枚举常量的对象也存储一个整数域。默认地,枚举中的每个常量都被赋予一个与其他常量不同的整数值。这些值按照设定它们时的顺序被赋给枚举常量,第一个常量从0开始,然后第二个常量是1,后面依此类推。通过调用常量的ordinal()方法就能获得它的整数值,但是一般来说不应该需要这样做。
可以使用equals()方法来比较枚举类型的整数值是否相等(但是,永远不要使用equals,直接使用==比较,因为我们定义了枚举类型就不希望再创建新常量对象了,直接使用已经定义好的实例)。例如,假设已经定义了枚举类型Season,其中包括了枚举常量spring、summer、fall和winter,可以编写如下内容:
Season now = Season.winter;
if(now.equals(Season.winter))
{
System.out.println("It is definitely winter!");
}
这个枚举类类型的equals()方法从Enum类继承而来,另外还继承了基于枚举类型实例的整数值进行比较的compareTo()方法。如果方 法调用的实例的整数值小于作为参数传入的实例,结果为负整数;如果它们相等,结果为0;如果当前实例的整数值大于作为参数传入的值,结果为正整数。因此, 当定义这些枚举常量时,它们的设定顺序决定了compareTo()方法实现的顺序。可以这样使用:
if(now.compareTo(Season.summer) > 0)
System.out.println("It is definitely getting colder!");
枚举引入的values()方法是一个属于枚举类类型的静态方法,该方法返回一个包括在基于集合的for循环中使用的所有枚举常量的集合对象。
2.1 添加成员到枚举类
因为枚举是类,所以在定义枚举类型时可以添加自己的方法和域,还可以添加属于自己的构造函数来初始化任何引入的额外域。下面看一个例子。假设想要为衣服(比如夹克)的尺寸定义一个枚举类型,初始的定义可能如下:
public enum JacketSize { small, medium, large, extra_large, extra_extra_large }
然后会发现,可能想要记录应用到每个夹克尺寸的平均胸围。可以将上面的枚举定义修改为如
下形式:
注意这里的枚举常量列表以分号结束。列表中的每个常量在括号中都有对应的胸围,而且这些值会被传递给添加到类中的构造函数。在之前的JacketSize 定义中,每个枚举常量的出现都会导致对枚举类默认构造函数的一次调用。
事实上,可以在每个常量名称的后面放一对空括号,这样仍然会编译。但是,这不会增加代码的清晰度。因为已经定义了一个构造函数,所以不会为枚举类型定义默认的构造函数。因此,不能只使用名称来编写枚举常量,必须在每个枚举常量的后面添加一对括号并在其中包括一个值作为胸围。当然,如果想要在枚举中选择省略一些常量的胸围尺寸,也可以定义自己的默认构造函数并且为chestSize 赋一个默认值。
即使已经添加了自己的构造函数,从基类Enum 中继承的用来存储常量名称及其整数值的域仍
然会被正确地设置。compareTo()方法实现的常量顺序仍然由定义中常量出现的顺序决定。注意决不能将枚举类中的构造函数声明为public。如果这样做,enum 类定义就不会被编译。唯一允许对定义为枚举的类的构造函数应用的修饰符是private,这导致只能在类的内部调用构造函数。
2.2 根据枚举值获取枚举类
这里用到了枚举的静态方法values()返回所有的枚举常量,还可以使用Day.class.getEnumConstants()实现同样的功能。
3. 枚举原理
枚举类型经过编译器编译之后产生的是一个final class文件,该类继承了java.lang.Enum<E>。所以定义自己的枚举类型时不能再extends其他父类。而每个枚举常量都被编译成枚举类的public static final **Enum类型的常量。
比如:
利用javap -s class文件可以看到:
注意其中的:
public final class com.an.service.render.MessageTypeEnum extends java.lan.Enum
public static final com.an.service.render.MessageTypeEnum Order_New;
4.枚举示例
http://www.iteye.com/topic/1116193
http://www.cnblogs.com/linjiqin/archive/2011/02/11/1951632.html
http://socket.blog.163.com/blog/static/209873004201061440047/
枚举通常替代常量定义有固定范围的常量。经常会用在switch语句中。
查看enum的字节码可以看到,每个枚举常量被编译为枚举类的静态常量。
参考:http://www.cnblogs.com/frankliiu-java/archive/2010/12/07/1898721.html
5.枚举序列化部分讨论
http://www.iteye.com/topic/1052055
http://wenku.baidu.com/link?url=qQBwVRubjTG6QsiqBszi7wyfVrZE9m2oLEpLpOgR9en-k9YIvrfR_Nx3MlYIG3Bs8YCp3JtnXwpQ4as_1o6juhHd0xCvcHTLD3F0hHQI_E_
6.枚举异常IllegalArgumentException
jdk1.6源码:
当调用valueOf,且name不是定义的枚举常量(注意是枚举常量,不是ordinal也不是括号内指定的别名)时会抛出IllegalArgumentException异常,且会打出日志:"No enum const " + enumType +"." + name
还可以参见:
http://stackoverflow.com/questions/12639791/what-is-the-reason-for-java-lang-illegalargumentexception-no-enum-const-class-e
1.枚举引入
通常需要一些只能从预定义的固定集合中取值的变量。例如,假设想要定义一个名为weekday的整型变量,用来存储表示星期几的整数值。该变量最好能限制在7个可能的值之内,每个值逐个对应星期一到星期日。这种情形下一种称作枚举类型(enumerated type),甚至简单地称作枚举(enumeration)的工具是自然的选择。可以使用如下声明语句为这种情况定义一个枚举:
enum Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
这里定义了一个新的类型Day,变量只能存储在括号中设定的其中一个值。名称Monday、
Tuesday 一直到Sunday 都称为枚举常量,而且它们标识了Day 类型的变量中仅允许的值。事实上,这些名称会对应到整数值,默认情况下从0 开始,但是它们与整型变量不同,因为它们只在枚举Day的上下文中存在。
注意:在Day 枚举定义的最后没有分号(如果枚举中还定义了其他成员,则必须有分号)。因为这里是定义一个类型,所以在反括号的后面不需要
添加分号。类型名Day 的开头使用一个大写的D,因为按照约定,定义的类型都以大写字母开头。
枚举常量的名称通常用全大写命名,对应了普通public final static常量的规则。
有了这个新类型,现在可以按照如下方式定义变量weekday:
Day weekday = Day.Tuesday;
这里声明了Day 类型的变量weekday 并且将其初始化为Tuesday。注意提供weekday 初始值的
枚举常量必须用枚举类型名限定(switch语句中的case后面使用枚举常量时不需要用枚举类型限定)。如果不要限定名,编译器就无法认出该常量。
枚举通常能包含所需要数目的枚举常量。这里是一个表示每年月份的枚举类型:
enum Month { January, February, March , April , May , June,
July , August , September, October, November, December }
可以按如下方式定义这种类型的变量:
Month current = Month.September; // Initialize to September
如果之后想要修改变量中存储的值,可以将其设置为一个不同的枚举常量:
current = Month.October;
current 变量现在包含枚举常量值October。
2.枚举使用
枚举类型其实是一种特殊形式的类,声明enum时不能继承一个超类,默认所有的枚举都自动地继承java.lang.Enum。在代码中定义枚举类型时,设定的枚举常量以一个类的实例被创建,这个类以java.lang包中的Enum类作为超类,所以跟类一样,在类的定义中可以放置枚举类型的定义,也可以将枚举类型定义放在一个单独的源文件中。
每个枚举常量对应的对象将常量的名称存储在一个域中,而枚举类类型从Enum类中继承toString()方法。Enum类中的toString()方法返回 枚举常量的原始名称,所以使用println()方法输出枚举常量时会获得枚举常量的名称。
表示枚举常量的对象也存储一个整数域。默认地,枚举中的每个常量都被赋予一个与其他常量不同的整数值。这些值按照设定它们时的顺序被赋给枚举常量,第一个常量从0开始,然后第二个常量是1,后面依此类推。通过调用常量的ordinal()方法就能获得它的整数值,但是一般来说不应该需要这样做。
可以使用equals()方法来比较枚举类型的整数值是否相等(但是,永远不要使用equals,直接使用==比较,因为我们定义了枚举类型就不希望再创建新常量对象了,直接使用已经定义好的实例)。例如,假设已经定义了枚举类型Season,其中包括了枚举常量spring、summer、fall和winter,可以编写如下内容:
Season now = Season.winter;
if(now.equals(Season.winter))
{
System.out.println("It is definitely winter!");
}
这个枚举类类型的equals()方法从Enum类继承而来,另外还继承了基于枚举类型实例的整数值进行比较的compareTo()方法。如果方 法调用的实例的整数值小于作为参数传入的实例,结果为负整数;如果它们相等,结果为0;如果当前实例的整数值大于作为参数传入的值,结果为正整数。因此, 当定义这些枚举常量时,它们的设定顺序决定了compareTo()方法实现的顺序。可以这样使用:
if(now.compareTo(Season.summer) > 0)
System.out.println("It is definitely getting colder!");
枚举引入的values()方法是一个属于枚举类类型的静态方法,该方法返回一个包括在基于集合的for循环中使用的所有枚举常量的集合对象。
2.1 添加成员到枚举类
因为枚举是类,所以在定义枚举类型时可以添加自己的方法和域,还可以添加属于自己的构造函数来初始化任何引入的额外域。下面看一个例子。假设想要为衣服(比如夹克)的尺寸定义一个枚举类型,初始的定义可能如下:
public enum JacketSize { small, medium, large, extra_large, extra_extra_large }
然后会发现,可能想要记录应用到每个夹克尺寸的平均胸围。可以将上面的枚举定义修改为如
下形式:
public enum JacketSize { small(36), medium(40), large(42), extra_large(46), extra_extra_large(48); // Constructor JacketSize(int chestSize) { this.chestSize = chestSize; } // Method to return the chest size for the current jacket size public int chestSize() { return chestSize; } private int chestSize; // Field to record chest size }
注意这里的枚举常量列表以分号结束。列表中的每个常量在括号中都有对应的胸围,而且这些值会被传递给添加到类中的构造函数。在之前的JacketSize 定义中,每个枚举常量的出现都会导致对枚举类默认构造函数的一次调用。
事实上,可以在每个常量名称的后面放一对空括号,这样仍然会编译。但是,这不会增加代码的清晰度。因为已经定义了一个构造函数,所以不会为枚举类型定义默认的构造函数。因此,不能只使用名称来编写枚举常量,必须在每个枚举常量的后面添加一对括号并在其中包括一个值作为胸围。当然,如果想要在枚举中选择省略一些常量的胸围尺寸,也可以定义自己的默认构造函数并且为chestSize 赋一个默认值。
即使已经添加了自己的构造函数,从基类Enum 中继承的用来存储常量名称及其整数值的域仍
然会被正确地设置。compareTo()方法实现的常量顺序仍然由定义中常量出现的顺序决定。注意决不能将枚举类中的构造函数声明为public。如果这样做,enum 类定义就不会被编译。唯一允许对定义为枚举的类的构造函数应用的修饰符是private,这导致只能在类的内部调用构造函数。
2.2 根据枚举值获取枚举类
public enum Day { A(1),B(2),C(5); private int value; Day(int value) { this.value = value; } public int getValue() { return value; } public static Day getEnumByValue(int value) { Day[] day = Day.values(); for (Day d : day) { if (d.getValue() == value) { return d; } } return null; } }
这里用到了枚举的静态方法values()返回所有的枚举常量,还可以使用Day.class.getEnumConstants()实现同样的功能。
3. 枚举原理
枚举类型经过编译器编译之后产生的是一个final class文件,该类继承了java.lang.Enum<E>。所以定义自己的枚举类型时不能再extends其他父类。而每个枚举常量都被编译成枚举类的public static final **Enum类型的常量。
比如:
public enum MessageTypeEnum { Order_New(1, "OrderPipe_ghost", 1, "abc"); private Integer index; private String topic; private Integer messageType; private String description; private static ConcurrentHashMap<String, Integer> messageTypeMap = null; static { messageTypeMap = new ConcurrentHashMap<String, Integer>(); for (MessageTypeEnum o: MessageTypeEnum.values()){ messageTypeMap.put(o.getTopic(),o.getMessageType()); } } public static Map<String, Integer> getMessageTypeMap(){ return messageTypeMap; } private MessageTypeEnum(Integer index, String topic, Integer messageType, String description) { this.index = index; this.topic = topic; this.messageType = messageType; this.description = description; } ... }
利用javap -s class文件可以看到:
ervice\render\MessageTypeEnum Compiled from "MessageTypeEnum.java" public final class com.an.service.render.MessageTypeEnum extends java.lan .Enum{ public static final com.an.service.render.MessageTypeEnum Order_New; Signature: Lcom/an/libra/service/render/MessageTypeEnum; public static com.an.service.render.MessageTypeEnum[] values(); Signature: ()[Lcom/an/libra/service/render/MessageTypeEnum; public static com.an.service.render.MessageTypeEnum valueOf(java.lang.Str ng); Signature: (Ljava/lang/String;)Lcom/an/libra/service/render/MessageTypeEnum; public static java.util.Map getMessageTypeMap(); Signature: ()Ljava/util/Map; public java.lang.Integer getIndex(); Signature: ()Ljava/lang/Integer; public void setIndex(java.lang.Integer); Signature: (Ljava/lang/Integer;)V public java.lang.String getTopic(); Signature: ()Ljava/lang/String; public void setTopic(java.lang.String); Signature: (Ljava/lang/String;)V public java.lang.Integer getMessageType(); Signature: ()Ljava/lang/Integer; public void setMessageType(java.lang.Integer); Signature: (Ljava/lang/Integer;)V public java.lang.String getDescription(); Signature: ()Ljava/lang/String; public void setDescription(java.lang.String); Signature: (Ljava/lang/String;)V static {}; Signature: ()V }
注意其中的:
public final class com.an.service.render.MessageTypeEnum extends java.lan.Enum
public static final com.an.service.render.MessageTypeEnum Order_New;
4.枚举示例
http://www.iteye.com/topic/1116193
http://www.cnblogs.com/linjiqin/archive/2011/02/11/1951632.html
http://socket.blog.163.com/blog/static/209873004201061440047/
枚举通常替代常量定义有固定范围的常量。经常会用在switch语句中。
查看enum的字节码可以看到,每个枚举常量被编译为枚举类的静态常量。
参考:http://www.cnblogs.com/frankliiu-java/archive/2010/12/07/1898721.html
5.枚举序列化部分讨论
http://www.iteye.com/topic/1052055
http://wenku.baidu.com/link?url=qQBwVRubjTG6QsiqBszi7wyfVrZE9m2oLEpLpOgR9en-k9YIvrfR_Nx3MlYIG3Bs8YCp3JtnXwpQ4as_1o6juhHd0xCvcHTLD3F0hHQI_E_
6.枚举异常IllegalArgumentException
jdk1.6源码:
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); }
当调用valueOf,且name不是定义的枚举常量(注意是枚举常量,不是ordinal也不是括号内指定的别名)时会抛出IllegalArgumentException异常,且会打出日志:"No enum const " + enumType +"." + name
还可以参见:
http://stackoverflow.com/questions/12639791/what-is-the-reason-for-java-lang-illegalargumentexception-no-enum-const-class-e
发表评论
-
slf4j 的MDC (附带主动获取方法堆栈)
2015-08-03 17:29 52921. 主动获取方法调用链 ... -
<java 序列化&反序列化> serialVersionUID的作用(转)
2015-02-11 18:12 1160参考: http://www.strutshome.com/i ... -
Class(ClassLoader)#getResource, getResourceAsStream
2014-10-31 17:04 2324一、Class#getResourceAsStream 1.1 ... -
自定义注解
2014-10-15 16:17 21971.Annotation(注解)介绍 Annotation(注 ... -
MD5 几种方法的选择
2014-03-07 12:13 6395md5加密实现方法有很多种,也导致很难选择。大概分析下自己了解 ... -
静态变量初始化 && 类实例初始化
2014-02-12 15:45 3618【本文整合多篇网文+验证扩展而成】 1. 静态变量(块)初始 ... -
<时间-2>Date & DateFormat & SimpleDateFormat & Calendar
2014-02-07 12:57 4003前面介绍了计算机世界 ... -
<时间-1>计算机世界中的时间概念
2014-01-22 22:59 3402在计算机中表示时间是 ... -
泛型编程
2014-01-04 10:47 1991参考资料:《java核心技术 卷1》 网络 Java中的泛型 ... -
我的烂笔头 -- java常识、常见问题
2013-08-23 12:15 15671.Integer.MAX_VALUE Integer ... -
<1> jdbc基础
2013-08-13 18:30 1487本来是正写着spring系列 ...
相关推荐
【Java面试】枚举从使用到原理
枚举硬件
暴力搜索内存 直接内存搜索枚举内存的原理和实现
自己编写一个用VC++枚举当前所有打开的程序窗口,其原理是利用GetWindowLong(hWnd,GWL_STYLE)& WS_VISIBLE对打开的窗口进行查找,并将窗口的句柄存放在一个HWND的数组中,结合EnumWindows进行窗口的枚举,从而得到...
本文介绍C# 枚举绑定到ComboBox下拉框的实际开发代码,是开发人员的实际经验总结;绑定原理也适用于其他开发语言,如:Java、C++等
简单介绍了DNS和ENUM的原理及在IMS网络中的使用
清晰的思路,详细介绍了onvif枚举设备的原理和分析。
主要介绍了Java枚举类接口实例原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
23.2 USB设备的枚举过程 23.3 USB标准设备请求 23.4 程序实现方法 第24章 完整的程序—闹钟的实现 24.1 简介 24.2 关键代码 附录A 使用许可证 附录B 本书配套光盘说明 参考文献 超星格式 书 + 源码+ 例子
主要介绍了Java实现接口的枚举类,结合实例形式分析了java接口的枚举类相关原理与使用技巧,需要的朋友可以参考下
c51_usb_hid_全套好资料,usb枚举过程+原理图+上位机+vc++源码+usb驱动源码。手把手教你写下位机、上位机、VC++源码,USB驱动源码,全部编译通过。内含USB HID 读写 测试工具(类似串口调试工具)及其源码。包括51...
主要介绍了 JAVA 枚举单例模式及源码分析的实例详解的相关资料,需要的朋友可以参考下
EnumSet是Java枚举类型的泛型容器,Java既然有了SortedSet、TreeSet、HashSet等容器,为何还要多一个EnumSet呢?答案肯定是EnumSet有一定的特性,举个例子,EnumSet的速度很快。其他特性不一一列举了,毕竟本文的...
分析了数据流降维算法PCA和KPCA的原理和实现方法。针对在大型数据集上PCA线性降维无法有效实现降维且KPCA的降维效率差,提出了一种新的降维策略GKPCA算法。该算法将数据集先分组,对每一组执行KPCA,然后过滤重新...
主板电路原理图EASY USB 51 PROGRAMER V1_1 SCH 51编程器上位机(源码)Easy USB 51 Programer Host_Src 51编程器上位机_Easy USB 51 Programer Host V1.0_DEMO bus hound 5.0 HEX文件(真正的实例—驱动我们的...
布尔代数和数字逻辑 计算机组成原理PPT教案.pptx
通过对底层原理的揭示,使您更进一步的理解Windows上各类程序的工作方式和如何进行错误诊断及性能优化。 本次课程的内容编排得到了国内知名技术作家,《Windows Internals》一书的中文译者,潘爱民先生的大力支持,...
通过对底层原理的揭示,使您更进一步的理解Windows上各类程序的工作方式和如何进行错误诊断及性能优化。 本次课程的内容编排得到了国内知名技术作家,《Windows Internals》一书的中文译者,潘爱民先生的大力支持,...
通过对底层原理的揭示,使您更进一步的理解Windows上各类程序的工作方式和如何进行错误诊断及性能优化。 本次课程的内容编排得到了国内知名技术作家,《Windows Internals》一书的中文译者,潘爱民先生的大力支持,...