不知大家是否见过这样一种让人“眼花缭乱”的位域操作,
int read = 0 << 1;
int write = 0 << 2;
int connect = 0<<3;
最典型的就是jdk nio里的SelectionKey了,当你判断一个selectionkey所感兴趣的操作时,你不得不像下面这样写
int interestSet = selectionKey.interestOps(); boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT; boolean isInterestedInConnect = (interestSet & SelectionKey.OP_CONNECT)== SelectionKey.OP_CONNECT; boolean isInterestedInRead = (interestSet & SelectionKey.OP_READ)== SelectionKey.OP_READ;boolean isInterestedInWrite = (interestSet & SelectionKey.OP_WRITE)== SelectionKey.OP_WRITE;
这段代码是不是看的有点头晕,并且当一个interestSet包含多个你事件时你就等着就去写长长的if else表达式吧,现在如果把这种情景换成EnumSet会是如何呢:
enum SelectionKey{ OP_ACCEPT,OP_CONNECT,OP_READ,OP_WRITE }
那么如果我们现在要一个对accept和connect事件感兴趣的interestSet我们只需要下面一行代码:
EnumSet<SelectionKey> interestSet = EnumSet.of(OP_ACCEPT,OP_CONNECT);
那么如何判断这个集合是否包含一个特定的操作呢?!别忘了我们的EnumSet继承了Set接口,Set接口提供了一个contains方法
interestSet.contains(SlectionKey.OP_READ); //false
如何遍历EnumSet?自行举一反三。
神马?你在担心性能?放心,EnumSet的底层是一个8byte的long型,一共64bit,这是啥意思呢,熟悉Enum的javaer都知道,Enum里面定义实例的顺序是敏感的,java.lang.Enum提供了一个ordinal方法,它会返回一个int值,代表这个enum实例在类里被定义的顺序,比如如果我调用SelectionKey的OP_ACCEPT的ordinal方法,那么它会返回1,现在回到EnumSet,上面我们定义了一个interestSet,里面包含了OP_ACCEPT和OP_CONNECT这两种我们感兴趣的操作,那么EnumSet的底层long的值为110000....(此处补齐64bit),如果你的Enum类定义的实例超过了64个,那么EnumSet会自动扩增!所以以后你可以尽请的使用Enum和EnumSet来代替位域操作啦!
原文地址:http://my.oschina.net/u/1160609/blog/290047