2007年6月16日星期六

What does <E extends Enum<E>> mean?

Enum的使用很简单,我们定义的enums实际上是继承了java.lang.Enum的类,所以才是类型安全和compile-timechecking。

稍微想了解一下Java是如何实现Enum的,所以打开java.lang.Enum的源代码,还没细看就先被类的声明吓了一跳。

public abstract class Enum<E extends Enum<E>>

implements Comparable<E>, Serializable

What does <E extends Enum<E>> mean?似乎是个递归的定义,google了一下,很快找到了一篇相关的文章,试着解释一下。

看不明白的,还是直接看原文吧。

1.Enum接受一个类型参数

2.Enum是一个抽象类,任何Enum的子类都必须为Enum提供一个类型参数

3.这个类型参数必须是Enum的子类

为什么要把范型定义搞的如此复杂呢?先看看这么做有什么好处。请看下面这两个类:

public abstract class TaxPayer<P extendsTaxPayer<P>>

{

protectedabstract P getDetailedType();

publicdouble extortCash()

{

return strategy.extortCash(getDetailedType());

}

}

public class Employee extends TaxPayer<Employee>

{



@Override

protectedEmployee getDetailedType()

{

return this;

}



}

在基类TaxPayer中声明了一个抽象方法getDetailedType(),强制要求子类覆盖这个方法,并且要求这个方法返回的是实际的子类。

也就是说,我们允许superclass定义这样的方法,它的参数和返回值可以是具体的子类,而不是基类。

我们可以看到,在TaxPayer的extortCash()方法中,通过getDetailedType()得到的实际上具体的子类。

这个基于范型实现的strategy模式,完整描述可以参考”Strategy Pattern with Generics“.

明白了上面的例子,你也就应该能够知道为什么java.lang.Enum被声明为Enum<Eextends Enum<E>>.

1.类型参数E被使用为getDeclaringClass()的返回值

2.类型参数E作为compareTo()的参数,看下面这个例子:

OpType opType = OpType.ADD;

ProductStatus status =ProductStatus.NORMAl;

opType.compareTo(status);

这儿直接就会报syntaxerror,compareTo的参数必须是OpType类型。这样,在基类的方法定义中,要求了方法参数是某个具体的子类。

简单的一个Enum,还包含了这样的设计技巧,看来JDK的代码还是要常翻出来看看。

没有评论: