zoukankan      html  css  js  c++  java
  • Java中的位掩码BitMask

    JDK源码的使用

    最近在JDK源码中闲逛,无意中看到了java.lang.reflect.Modifier这个类,这个类很简单,都是些常量定义和判断方法,于是扒了扒代码实现的含义,我们就看个isPublic方法吧:

    /**
     * Return {@code true} if the integer argument includes the
     * {@code public} modifier, {@code false} otherwise.
     *
     * @param   mod a set of modifiers
     * @return {@code true} if {@code mod} includes the
     * {@code public} modifier; {@code false} otherwise.
     */
    public static boolean isPublic(int mod) {
        return (mod & PUBLIC) != 0;
    }
     /**
     * The {@code int} value representing the {@code public}
     * modifier.
     */
    public static final int PUBLIC = 0x00000001;
     /**
     * The {@code int} value representing the {@code static}
     * modifier.
     */
    public static final int STATIC = 0x00000008;
    
    /**
     * The {@code int} value representing the {@code final}
     * modifier.
     */
    public static final int FINAL  = 0x00000010;
    

    我们来看看java.lang.Class类中的几个方法:

    public boolean isAnnotation() {
        return (getModifiers() & ANNOTATION) != 0;
    }
    
    public boolean isEnum() {
        // An enum must both directly extend java.lang.Enum and have
        // the ENUM bit set; classes for specialized enum constants
        // don't do the former.
        return (this.getModifiers() & ENUM) != 0 &&
        this.getSuperclass() == java.lang.Enum.class;
    }
    

    可以看到Class的getModifier()方法返回的整形值又能判断当前类是否是Enum,又能判断是否是Annotation。

    Modifier中定义了很多modifier的值,这些值都很有规律,从前往后依次都是2的n次方的16进制表示,也就是二进制的1每次左移的结果。最后的效果就是不同类型的modifier都在二进制形式的值中占一位。比如:

    PUBLIC:   0x00000001,二进制:0001
    PRIVATE:  0x00000002,二进制:0010
    PROTECTED:0x00000004,二进制:0100
    STATIC:   0x00000008,二进制:1000
    

    如果想表示一个类既是public又是static的时候,这时候getModifier()方法就会返回1001也就是整形9,而我们可以通过9的二进制表示来做位运算,就是文章开头的函数:

    public static boolean isPublic(int mod) {
        return (mod & PUBLIC) != 0;
    }
    

    这时候传入的mod为9,也就是1001,而public修饰符定义的值为0001,这两者做与运算的时候返回就是0001,该结果不为0,即当前方式是有public修饰符的。

    至此,这种由单个值表示多种状态的方式就叫做Java中的位掩码。

    日常工作中的使用

    例如,在一个系统中,用户一般有查询(Select)、新增(Insert)、修改(Update)、删除(Delete)四种权限,四种权限有多种组合方式,也就是有16中不同的权限状态(2的4次方)。

    一般情况下会想到用四个boolean类型变量来保存:

    public class Permission {
    	// 是否允许查询
    	private boolean allowSelect;
    	// 是否允许新增
    	private boolean allowInsert;
    	// 是否允许删除
    	private boolean allowDelete;
    	// 是否允许更新
    	private boolean allowUpdate;
    }
    

    但是如果使用位掩码的话,就可以用和Modifier类相似的方式了(1表示允许,0表示不允许):

    public class NewPermission {
        public static final int ALLOW_SELECT = 1 << 0; // 0001
        public static final int ALLOW_INSERT = 1 << 1; // 0010
        public static final int ALLOW_UPDATE = 1 << 2; // 0100
        public static final int ALLOW_DELETE = 1 << 3; // 1000
        	
        // 存储目前的权限状态
        private int flag;
        
        // 重新设置权限
        public void setPermission(int permission) {
            flag = permission;
        }
        
        // 添加一项或多项权限,比如当前只有select(0001),增加insert(0010)
        // 0001
        // 0010 |
        // 0011 = 即可以select也可以insert 
        public void enable(int permission) {
            flag |= permission;
        }
        	
        // 删除一项或多项权限,比如当前可以select、insert(0011),去掉insert()
        // 0010
        // 1101 ~
        // 0011 &
        // 0001 = 即只可以select了
        public void disable(int permission) {
            flag &= ~permission;
        }
        	
        // 是否拥某些权限
        public boolean isAllow(int permission) {
            return (flag & permission) == permission;
        }
        	
        // 是否禁用了某些权限
        public boolean isNotAllow(int permission) {
            return (flag & permission) == 0;
        }
        	
        // 是否仅仅拥有某些权限
        public boolean isOnlyAllow(int permission) {
            return flag == permission;
        }
    }
    

    今天分享的就是这样一个小细节,希望对大家有帮助。

  • 相关阅读:
    C#/Net代码精简优化技巧(二)【转】
    IsSpecialName特性及其他问题【转】
    &、|与&&、||的比较
    序列化后存储Cookie
    序列化反序列化操作
    C#/Net代码精简优化技巧(一)【转】
    .Net 中的序列化与反序列化【转】
    c#对象序列化(二进制序列化)BinaryFormatter【转】
    POJ 2828 Buy Tickets(单点更新) 详细题解和思路
    Color the ball HDU 1556 (非线段树做法)
  • 原文地址:https://www.cnblogs.com/mrcharleshu/p/13233150.html
Copyright © 2011-2022 走看看