Weitere ähnliche Inhalte Mehr von wang hongjiang (18) Enum开锁2. com.alibaba.common.lang.enumeration.Enum
为何会导致死锁 ?
JVM 规范:类初始化过程是唯一的。
当多个线程同时对某个类进行初始化时,只有一个线
程能够进行了 clinit ,其他线程会检测并等待,当
发现类已经被初始化完毕了它们不会再次执行
clinit 。
简单的说,导致死锁的原因是因为线程 A 在对我们的
Enum 中进行 clinit 时调用的方法要获取一个锁
L ,而锁 L 正被线程 B 占用,同时线程 B 又正要访
问这个 Enum 类成员,发现 Enum 类正在被线程
A 初始化,于是线程 B 等待线程 A 。
结果成了相互等待。
4. Java5 中的 enum 关键字
用 enum 关键字定义的一个枚举类型并不是真
的在 java 中创建了一种新的类型, enum
类型本质上仍是一个 class
把它当作一种特殊的 class 来对待。
( 编译器在会将 enum 转换为 class)
在 C, C# 中 enum 类型都是作为值类型的,
而 java 中 enum 是引用类型;
5. 关于 Java.lang.Enum
Enum 是所有 Java 语言枚举类型的公共基本类
:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable
Enum 被标记为 abstract ,但实际上并没有包含
任何 abstract 方法。这是为何?
所使用的泛型表达式又如何理解?
6. 关于 Java.lang.Enum
Enum 实现了 Comparable 和 Serializable 接口。
Enum 的构造函数是 protected 。
protected Enum(String name,int ordinal)
除了 toString 方法,其他方法都是 final 的。
用户不能自行继承 Enum 类,编译报错。只能通过
enum 来定义枚举。
7. Java.lang.Enum 的 name() 方法
返回此枚举常量的名称,在其枚举声明中对其
进行声明。 与此方法相比,大多数程序
员应该优先考虑使用 toString() 方法
,因为 toString 方法返回更加用户友
好的名称。该方法主要设计用于特殊情形
,其正确性取决于获取正确的名称,其名称
不会随版本的改变而改变。
8. enum 中的静态方法 : valueOf,values
Java.lang.Enum 中包含:
public static <T extends Enum<T>> T valueOf(Class
<T> enumType, String name)
对于每个继承 Enum 的实际枚举,编译器会自动增加一个静态的方法:
public static <T extends Enum<T>> T
valueOf(String name)
相比 Enum 的 valueOf 少了第一个 enumType 参数,因为这个已经是
确定的了。
values() 静态方法:这个静态方法 java.lang.Enum 中没有,是编译器
增加到 enum 中的,返回枚举数组。
10. enum 获取某个属性的方式
1) 定义该属性为成员变量,在构造函数中设置该属性,通过 getXXX
方式来获取。 eg:
public enum OfferTypeEnum {
/** 求购 */
SALE("SALE"),
/** 供应 */
BUY("BUY"),
/** 类型:合作 */
MISC("MISC"),
……
public String getName() {
return this.name;
}
11. 2) Switch 方式判断。(容易维护)
public enum OfferTypeEnum {
SALE, BUY, MISC;
public String getName() {
switch(this){
case SALE:
return "SALE";
case BUY:
return "BUY";
case MISC:
return "MISC";
}
return "";
}
效率方面,第 2 种每次都需要比较,第 1 种采用空间换时间的方式
。
我们采用第一种方式。
12. 将字符串解析为 enum
EnumUtil 工具类中的 getEnumByName ,等方法
返回值都是旧的 Enum 类型。
对应的,增加了 JdkEnumUtil 工具类
使用 其中的 valueOf 函数来将字符串解析为新的枚
举。
但对于那些枚举变量名和 name 属性不一致的情况,
应该在相应的枚举中提供 parse 方法,比如:
13. OfferTypeEnum 中:
/** 类型:代理 */
AGENT(“AGEN”), // 这里是前人犯的错误,兼容以前的代码
需要该类自行提供一个解析方法:
public static OfferTypeEnum parse(String str){
if(str == null) return null;
if (str.equals("AGEN") || str.equals("AGENT"))
return AGENT;
return
(OfferTypeEnum)JdkEnumUtil.valueOf(OfferTyp
eEnum.class, str);
}
15. Java5 的 enum 为何不能继承?
会员类型:
免费会员
中文站会员类型: 国际站会员类型:
Free+, 诚信通 中供
Java5 的 enum 是不可以继承的,无法通过继承的方式来复用,因为它破坏
了类型的一致性。
子类和父类类型不同。枚举的值必须是相同类型
enum 类型的 class.getModifiers() 是包含 final 修饰符的。
(编译器将 enum 转为 final class ,确保它无法继承。 )
17. 使用 shell 来检测重构后枚举名称是否写错
Distill-trunk.sh Distill-branch.sh Javafile
Checknew.sh Checkunmatchedref.sh Getunmatched.sh
Hinweis der Redaktion 1 )为何 Enum 声明为 abstract ,我也不很清楚。可能是限制我们对 Enum 的使用,也可能是给编译器用的,类似于某些标记接口。 2 )这个泛型表达式表示 泛型参数型必须是 Enum 泛型类的子类,这个地方要看看 java 规范,了解的不深。 弄清楚关于泛型的几个术语: 1. Type Parameters 2. Type Variables 3. Type Arguments 4. Parameterized Types 5. Bounds