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;
    }
}
今天分享的就是这样一个小细节,希望对大家有帮助。
Java中的位掩码BitMask的更多相关文章
- 位掩码(BitMask)的介绍与使用
		
一.前言 位运算在我们实际开发中用得很少,主要原因还是它对于我们而言不好读.不好懂.也不好计算,如果不经常实践,很容易就生疏了.但实际上,位运算是一种很好的运算思想,它的优点自然是计算快,代码更少. ...
 - Java中的位运算及简单的算法应用介绍
		
众所周知,计算机底层是二进制.而java作为一门计算机编程语言,也对二进制的位运算提供了完整的支持. 在java中,int是32位的,也就是说可以用来实现32位的位运算.方便起见,我们一般用16进制对 ...
 - Java中的位运算符 &、|、^、~、<< 和 >>
		
一.& 按位与运算符 5 & 3 = 1 5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101 3转换为二进制:0000 0000 0000 ...
 - Java中的位运算符
		
Java提供的位运算符有:左移( << ).右移( >> ) .无符号右移( >>> ) .位与( & ) .位或( | ).位非( ~ ).位异或( ...
 - Java中的位运算符、移位运算
		
一.位运算 Java中有4个位运算,它们的运算规则如下: (1)按位与 (&) :两位全为1,结果为1,否则为0: (2)按位或 (|) :两位有一个为1,结果为1,否则为0: (3) ...
 - Java中的位运算
		
昨天去面试的时候做到了一道Java的位运算题目,发现有个运算符不懂:">>>",今天特地查了一下,并小结一下常见的位运算符号: ~ 按位非(NOT)(一元运算) ...
 - Java中符号位扩展
		
第一个例子: byte b=-100;b在内存中是以补码的形式存贮的:1001 1100 如果执行char c=(char)b;如3楼企鹅先生所说:b要先变为int,这时增加的位全要用b的符号位填充( ...
 - java中的位运算及移位运算
		
为了方便对二进制位进行操作,Java给我们提供了以下四个二进制位操作符: & 按位与 | 按位或 ^ 按位异或 ~ 按位取反 Java中有三个移位运算符: 左移:&l ...
 - Java中关于位运算的面试题
		
位运算的效率是最高的,因为位位运算是直接对二进制进行操作 位运算只能应用于整型和char类型(char类型可以看做是特殊的无符号的整形) 面试题: a: 判断一个数是否是奇数 a & 1 == ...
 
随机推荐
- Spring Boot 加载application.properties顺序
			
1.准备四份application.properties a.项目根目录下config/application.properties ,内容为: test.user.name = a b.项目根目录 ...
 - Luogu P3200 [HNOI2009]有趣的数列
			
题意 给定 \(n\),求有多少个长度为 \(2n\) 的排列 \(p\) 满足 对于 \(1\leq i\leq n\),\(p_{2i-1}<p_{2i}\). \(p_1<p_3&l ...
 - RabbitMQ相关概念的理解
			
1.什么是消息? 消息就是程序(服务)之间传递的数据(图/文/声/像). 2.MQ是什么? MQ(MessageQueue)是指消息队列亦或消息总线.是消息的容器,这个容器的策略是FIFO(先进先出) ...
 - Es6-Promise初识
			
Promise 含义: Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Pro ...
 - 直播平台源码搭建教程:微信小程序中的直播如何去掉水印
			
直播平台源码搭建教程:微信小程序中的直播如何去掉水印 本文与大家分享一下直播平台源码搭建教程,如何去掉直播视频的水印 var services = require('../../lib/service ...
 - leetcode110:combination-sum-ii
			
题目描述 给出一组候选数C和一个目标数T,找出候选数中起来和等于T的所有组合. C中的每个数字在一个组合中只能使用一次. 注意: 题目中所有的数字(包括目标数T)都是正整数 组合中的数字 (a 1, ...
 - # Maven:Could not transfer artifact org.springframework:spring-webmvc:pom:。。。(系统找不到文件),从网上clone到本地的项目报红
			
解决办法: 确保maven配置正确,在maven的setting.xml配置文件中, 配置本地仓库路径 <localRepository>D:\Maven\文件名</localRep ...
 - .NetMvc从http或本地下载pdf文件
			
1.帮助类 1 public static class PdfHelper 2 { 3 #region 从http链接下载 4 public static void Download(string u ...
 - IO流读写数据简单示例
			
常用的字节输入流有:InputStream ,FileInputStream,BufferedInputStream 常用的字节输出流有:OutputStream,FileOutputStream,B ...
 - 数字取证autopsy系列——保存证据镜像(一)
			
简介: 在学习autopsy之前,我们先学习如何将犯罪嫌疑人的磁盘保存为一个证据镜像.我们使用的将磁盘保存为证据镜像的工具为AccessData FTK imager,你可以自行搜索下载. Acces ...