简介很多人都用过java中的枚举。枚举是JAVA1.5中引用的一种新类型,用来表示枚举作用域,但是可能很少有人知道java中enum是怎么工作的,enum和Enum是什么关系?枚举可以扩展吗?一起来看看吧。enum和EnumJAVA1.5中引入了枚举类。我们通常使用enum关键字来定义一个枚举类:publicenumStatusEnum{START(1,"start"),INPROCESS(2,"inprocess"),END(3,"end");私有整数代码;私有字符串描述;StatusEnum(intcode,Stringdesc){this.code=code;这个.desc=desc;}}在上面的枚举类中,我们自定义了构造函数,定义了3个枚举对象。接下来,让我们看看如何使用这个枚举类:publicstaticvoidmain(String[]args){StatusEnumstart=START;System.out.println(start.name());System.out.println(start.ordinal());System.out.println(start.code);System.out.println(start.desc);}code和desc的输出很容易理解,因为这是我们自定义枚举类中的属性,但是name和ordinal是什么?哪儿来的呢?这里要介绍java.lang.Enum类,它是JAVA中所有enum枚举类的父类。name()和ordinal()方法在此类中定义:publicfinalintordinal(){returnordinal;}publicfinalStringname(){返回名称;其中ordinal表示枚举在枚举类中的位置,那么就是枚举在枚举类中的名称。在上面的例子中,START的两个值分别是1和START。我们看一下Enum类的定义:publicabstractclassEnum>implementsComparable,SerializableInput是一个抽象类,但是编译器不允许你继承这个类。如果强行继承,会报错:Classescannotdirectlyextend'java.lang.Enum'所以,大家一定要记住,扭瓜不甜。其实不仅Enum类本身不能被继承,上面创建的枚举类StatusEnum也是不能被继承的。这会导致什么问题?如果枚举包含在外部jar包中,则无法扩展枚举。在某些特定情况下,此类限制可能会造成一些不便。好在netty也意识到了这个问题。接下来看看netty是怎么解决的。netty中的可扩展Enum:ConstantPool在Netty中表示常量的类称为Constant,它有两个属性,ID和name:publicinterfaceConstant>extendsComparable{intid();Stringname();}存放这些Constants的叫做ConstantPool。ConstantPool中有一个ConcurrentMap来保存具体的Constants。我们看一下ConstantPool的工厂类方法valueOf:publicTvalueOf(Stringname){returngetOrCreate(checkNonEmpty(name,"name"));}valueOf方法传入创建的Constant的名称。然后调用getOrCreate方法创建一个新的Constant:privateTgetOrCreate(Stringname){Tconstant=constants.get(name);if(constant==null){finalTtempConstant=newConstant(nextId(),name);constant=constants.putIfAbsent(name,tempConstant);如果(常量==null){返回tempConstant;}}返回常量;可以看到getOrCreate是从常量Map中创建并获取新创建的常量对象。使用ConstantPoolConstantPool是一个抽象类。如果我们需要创建一个新的枚举类池,我们可以直接继承ConstantPool,并在其中实现newConstant方法。下面是一个具体的用法示例:publicfinalclassFooextendsAbstractConstant{Foo(intid,Stringname){super(id,name);}}publicfinalclassMyConstants{privatestaticfinalConstantPoolpool=newConstantPool(){@OverrideprotectedFoonewConstant(intid,Stringname){returnnewFoo(id,name);}};publicstaticFoovalueOf(Stringname){returnpool.valueOf(name);}publicstaticfinalFooA=valueOf("A");publicstaticfinalFooB=valueOf("B");}privatefinalclassYourConstants{publicstaticfinalFooC=MyConstants.valueOf("C");publicstaticfinalFooD=MyConstants.valueOf("D");}在上面的例子中,我们创建的枚举类继承自AbstractConstant,然后自定义ConstantPool,从中可以返回新创建的Foo对象。在实时中,nettychannel中经常使用的ChannelOption是AbstractConstant的子类。让我们简单地看一下实现:publicclassChannelOptionextendsAbstractConstant>{privatestaticfinalConstantPool>pool=newConstantPool>(){@OverrideprotectedChannelOption