位掩码的思考第一章 一堆废话第01节 引子最近两天在写代码的过程中使用到了 定位功能在集成了 三方SDK 的过程中我发现需要申请多个权限多个权限全部通过的情况下才能完成这个功能。接下来我一顿操作猛如虎写了三个权限的申请。如 我想要完成定位我需要三个权限精准定位内部存储后台弹窗也就是说 我需要 三个权限全部通过我才能正常使用我的软件 只要有一个没有通过将无法使用。我考虑到别人做权限校验的过程中出现了 红叉 绿勾 标注清楚的情况。如图如果常规的做法很简单多个 boolean 值直接判断一下就可以了。但是如果增加了条件呢如何处理能否用一个数据去记录 当前哪些权限开启了哪些权限未开启我在想 如果我写了一个 函数方法用于校验所有的权限。checkPermissions()反馈一个值给外部调用者外部只需要通过一个值就明确知晓什么权限开启了什么权限未开启。我也在想如果这个值可以通过网络传输 或者 本地数据库记录。能否用一个值完整的记录下来这个内容呢以前的想法很可能就是写一个boolean[]布尔数组记录下来哪些权限是开启的哪些权限是关闭的。但是目前我就想使用一个数据值去记录多个状态。 这里的想法突然我想到了 Linux 操作系统 中 文件权限管理chmod 775 myscript.sh我就想 我们能否用一个 整数它的二进制位数去表示当前的权限选择呢。0000_0000_0000_0000_1111_0101_0000_0000这样的数据中不就是 由0和1去表示的 权限位。0是不允许1是允许如果我最开始的时候就约定了 3号位置代表是 “精确定位” 5号位置代表是 “内部存储” 6号位置代表是 “后台弹窗”通过对应位置的 0 和 1 确定这个是否被授权。 好像也可以啊然后我将整个 0和1 组成的数据转换成为一个十进制的数据进行存储数据库 或者 传输网络相比之下是不是 比 传递一堆的数据更小更快好像是可以的通过前面的介绍我试着找了相关的资料知晓了这种方案有个专属的名词 【位掩码】专业的定义:位掩码Bitmask是计算机科学中一种利用二进制位0 和 1来高效记录、修改和查询多个开关状态或布尔条件的技术。第02节 理解既然前面知道了 位掩码那么我们能不能更直观的从 人的角度去看待应用位掩码帮我们做事情呢为了更好的去学习 位掩码我想到了一个相对而言比较贴合的例子。现实生活中如果 您会下象棋应该知道象棋一共有 32颗 棋子。 他们分别是能否用一个 int 类型的数据来表示整个棋盘中棋子的存活呢 存在是 1 不存在是 0因为 int 类型的数据正好是 32位下面是我用 Java 代码定义的数据。为了方便于大家理解这段代码的意思我采用 xlsx 来表示内容。也就是说我们采用给个位数表示了每一颗 棋子的 存活状态。第二章 案例代码第01节 位掩码的工具类包含有 5 个方法序号方法名称方法作用举例说明1int addData(int currentMask, int targetData)添加数据参数1当前模板参数2十进制数2int removeData(int currentMask, int targetData)删除数据参数1当前模板参数2十进制数3boolean containsData(int currentMask, int targetData)判断模板中存在数据参数1当前模板参数2十进制数4ListString maskToAvailableList(int currentMask, MapString, Integer businessMap)转换 十进制 转 映射值参数1当前模板参数2映射表5String to32BitString(int number)将十进制数据转换为二进制字符串参数十进制数据代码importjava.util.ArrayList;importjava.util.List;importjava.util.Map;publicclassBitmaskUtil{/** * 1. 添加数据将某位置为 1 * 对应业务棋子入场、开启某权限、记录某数据存在 * 换算公式currentMask | targetData */publicstaticintaddData(intcurrentMask,inttargetData){returncurrentMask|targetData;}/** * 2. 剔除数据将某位置为 0 * 对应业务棋子死亡离场、关闭某权限、擦除某数据 * 换算公式currentMask ~targetData */publicstaticintremoveData(intcurrentMask,inttargetData){returncurrentMask~targetData;}/** * 3. 检查数据是否存在/存活判断某位是否为 1 * 换算公式(currentMask targetData) targetData */publicstaticbooleancontainsData(intcurrentMask,inttargetData){return(currentMasktargetData)targetData;}/** * 4. 转换数据【十进制整数 - 存活数据列表】 * 传入标准的业务字典配置表解析出当前整数里到底活着哪些数据 * * param currentMask 当前的十进制掩码 * param businessMap 业务配置字典Key为数据名称Value为位权重如 1, 2, 4, 8... */publicstaticListStringmaskToAvailableList(intcurrentMask,MapString,IntegerbusinessMap){ListStringactiveListnewArrayList();for(Map.EntryString,Integerentry:businessMap.entrySet()){if(containsData(currentMask,entry.getValue())){activeList.add(entry.getKey());}}returnactiveList;}/** * 5. 辅助工具获取精细的 32 位二进制字符串高位补0便于调试观察 */publicstaticStringto32BitString(intnumber){returnString.format(%32s,Integer.toBinaryString(number)).replace( ,0);}}第02节 映射规范类importjava.util.LinkedHashMap;importjava.util.Map;/** * 映射的规范业务规范 */publicclassSpecification{// 业务配置表publicstaticfinalMapString,IntegerconfigurationTablenewLinkedHashMap();// // 1. 黑方 16 枚棋子位定义交换后占据低 16 位即 1 0 到 1 15// // --- 底线 (九个位置) ---publicstaticfinalintB_JU_LEFT10;// 黑左车publicstaticfinalintB_MA_LEFT11;// 黑左马publicstaticfinalintB_XIANG_LEFT12;// 黑左象publicstaticfinalintB_SHI_LEFT13;// 黑左士publicstaticfinalintB_JIANG14;// 黑将 (居中无左右)publicstaticfinalintB_SHI_RIGHT15;// 黑右士publicstaticfinalintB_XIANG_RIGHT16;// 黑右象publicstaticfinalintB_MA_RIGHT17;// 黑右马publicstaticfinalintB_JU_RIGHT18;// 黑右车// --- 炮线 (两个位置) ---publicstaticfinalintB_PAO_LEFT19;// 黑左炮publicstaticfinalintB_PAO_RIGHT110;// 黑右炮// --- 卒线 (五个位置) ---publicstaticfinalintB_ZU_1111;// 黑卒1publicstaticfinalintB_ZU_2112;// 黑卒2publicstaticfinalintB_ZU_3113;// 黑卒3 (居中)publicstaticfinalintB_ZU_4114;// 黑卒4publicstaticfinalintB_ZU_5115;// 黑卒5// // 2. 红方 16 枚棋子位定义交换后占据高 16 位即 1 16 到 1 31// // --- 底线 (九个位置) ---publicstaticfinalintR_JU_LEFT116;// 红左车publicstaticfinalintR_MA_LEFT117;// 红左马publicstaticfinalintR_XIANG_LEFT118;// 红左相publicstaticfinalintR_SHI_LEFT119;// 红左仕publicstaticfinalintR_SHUAI120;// 红帅 (居中无左右)publicstaticfinalintR_SHI_RIGHT121;// 红右仕publicstaticfinalintR_XIANG_RIGHT122;// 红右相publicstaticfinalintR_MA_RIGHT123;// 红右马publicstaticfinalintR_JU_RIGHT124;// 红右车// --- 炮线 (两个位置) ---publicstaticfinalintR_PAO_LEFT125;// 红左炮publicstaticfinalintR_PAO_RIGHT126;// 红右炮// --- 兵线 (五个位置) ---publicstaticfinalintR_BING_1127;// 红兵1publicstaticfinalintR_BING_2128;// 红兵2publicstaticfinalintR_BING_3129;// 红兵3 (居中)publicstaticfinalintR_BING_4130;// 红兵4publicstaticfinalintR_BING_5131;// 红兵5static{// 填充黑方 configurationTable.put(黑左车,B_JU_LEFT);configurationTable.put(黑左马,B_MA_LEFT);configurationTable.put(黑左象,B_XIANG_LEFT);configurationTable.put(黑左士,B_SHI_LEFT);configurationTable.put(黑将,B_JIANG);configurationTable.put(黑右士,B_SHI_RIGHT);configurationTable.put(黑右象,B_XIANG_RIGHT);configurationTable.put(黑右马,B_MA_RIGHT);configurationTable.put(黑右车,B_JU_RIGHT);configurationTable.put(黑左炮,B_PAO_LEFT);configurationTable.put(黑右炮,B_PAO_RIGHT);configurationTable.put(黑卒1,B_ZU_1);configurationTable.put(黑卒2,B_ZU_2);configurationTable.put(黑卒3,B_ZU_3);configurationTable.put(黑卒4,B_ZU_4);configurationTable.put(黑卒5,B_ZU_5);// 填充红方 configurationTable.put(红左车,R_JU_LEFT);configurationTable.put(红左马,R_MA_LEFT);configurationTable.put(红左相,R_XIANG_LEFT);configurationTable.put(红左仕,R_SHI_LEFT);configurationTable.put(红帅,R_SHUAI);configurationTable.put(红右仕,R_SHI_RIGHT);configurationTable.put(红右相,R_XIANG_RIGHT);configurationTable.put(红右马,R_MA_RIGHT);configurationTable.put(红右车,R_JU_RIGHT);configurationTable.put(红左炮,R_PAO_LEFT);configurationTable.put(红右炮,R_PAO_RIGHT);configurationTable.put(红兵1,R_BING_1);configurationTable.put(红兵2,R_BING_2);configurationTable.put(红兵3,R_BING_3);configurationTable.put(红兵4,R_BING_4);configurationTable.put(红兵5,R_BING_5);}}第03节 测试类如何使用上述的几个方法呢importjava.util.List;publicclassDemo{publicstaticvoidmain(String[]args){intFULL0XFFFF_FFFF;intZERO0X0000_0000;// 在空棋盘当中, 放入了两个数据红左车 和 红帅 返回的结果是一个十进制的整数intaddDataBitmaskUtil.addData(ZERO,Specification.R_JU_LEFTSpecification.R_SHUAI);// 输出当前的十进制整数System.out.println(addData addData);// 将十进制的整数, 转换成为二进制的数据32位的0和1组成 如果存在是1, 如果不存在是 0Stringstr32addBitmaskUtil.to32BitString(addData);// 输出当前的二进制System.out.println(str32add str32add);// 将当前的数据, 转换成为映射中存在的数据值, 从映射表当中查找 存在的数据值ListStringlistAddBitmaskUtil.maskToAvailableList(addData,Specification.configurationTable);// 输出当前的映射值System.out.println(listAdd listAdd);System.out.println();// 在满棋盘当中, 移除掉数据红帅 和 红右士 返回的结果是一个十进制的整数intremoveDataBitmaskUtil.removeData(FULL,Specification.R_SHUAISpecification.R_SHI_RIGHT);// 输出当前的十进制System.out.println(removeData removeData);// 将十进制的整数, 转换成为二进制的数据32位的0和1组成 如果存在是1, 如果不存在是 0Stringstr32removeBitmaskUtil.to32BitString(removeData);// 输出当前的二进制System.out.println(str32remove str32remove);// 将当前的数据, 转换成为映射中存在的数据值, 从映射表当中查找 存在的数据值ListStringlistRemoveBitmaskUtil.maskToAvailableList(removeData,Specification.configurationTable);// 输出当前的映射值System.out.println(listRemove listRemove);// 查找当前的数据中, 是否包含有 需要查找的数据booleancontainsDataBitmaskUtil.containsData(removeData,Specification.R_SHUAI);// 输出查找的结果System.out.println(containsData containsData);}}第04节 最终输出结果addData 1114112 str32add 00000000000100010000000000000000 listAdd [红左车, 红帅] removeData -3145729 str32remove 11111111110011111111111111111111 listRemove [黑左车, 黑左马, 黑左象, 黑左士, 黑将, 黑右士, 黑右象, 黑右马, 黑右车, 黑左炮, 黑右炮, 黑卒1, 黑卒2, 黑卒3, 黑卒4, 黑卒5, 红左车, 红左马, 红左相, 红左仕, 红右相, 红右马, 红右车, 红左炮, 红右炮, 红兵1, 红兵2, 红兵3, 红兵4, 红兵5] containsData false第三章 后续操作第01节 拓展关于后续如果作为一个应用而言我们只需要1、拿着工具类 2、根据自己的业务自定义配置项应该就可以完成大部分的 实际需求。例如前面我定义的几个条件当然可能会更多。精准定位内部存储后台弹窗就可以修改配置项作为条件直接采用工具类应该是可以完成对应的 位掩码权限管理。第02节 深思方向1如果我们想要深入的理解整个操作那么可以专门去研究一下位运算的操作。 也就是关于工具类中的几个 运算符。方向2如果我没有那么多的条件选项我该如何呢 或者说我改为 16位的 short 甚至是 8位的 byte 亦或者是 64 位的 long方向3当前我写的是 Java 的版本如果我们操作的其他的语言呢 例如 C语言C等。
位掩码的思考
位掩码的思考第一章 一堆废话第01节 引子最近两天在写代码的过程中使用到了 定位功能在集成了 三方SDK 的过程中我发现需要申请多个权限多个权限全部通过的情况下才能完成这个功能。接下来我一顿操作猛如虎写了三个权限的申请。如 我想要完成定位我需要三个权限精准定位内部存储后台弹窗也就是说 我需要 三个权限全部通过我才能正常使用我的软件 只要有一个没有通过将无法使用。我考虑到别人做权限校验的过程中出现了 红叉 绿勾 标注清楚的情况。如图如果常规的做法很简单多个 boolean 值直接判断一下就可以了。但是如果增加了条件呢如何处理能否用一个数据去记录 当前哪些权限开启了哪些权限未开启我在想 如果我写了一个 函数方法用于校验所有的权限。checkPermissions()反馈一个值给外部调用者外部只需要通过一个值就明确知晓什么权限开启了什么权限未开启。我也在想如果这个值可以通过网络传输 或者 本地数据库记录。能否用一个值完整的记录下来这个内容呢以前的想法很可能就是写一个boolean[]布尔数组记录下来哪些权限是开启的哪些权限是关闭的。但是目前我就想使用一个数据值去记录多个状态。 这里的想法突然我想到了 Linux 操作系统 中 文件权限管理chmod 775 myscript.sh我就想 我们能否用一个 整数它的二进制位数去表示当前的权限选择呢。0000_0000_0000_0000_1111_0101_0000_0000这样的数据中不就是 由0和1去表示的 权限位。0是不允许1是允许如果我最开始的时候就约定了 3号位置代表是 “精确定位” 5号位置代表是 “内部存储” 6号位置代表是 “后台弹窗”通过对应位置的 0 和 1 确定这个是否被授权。 好像也可以啊然后我将整个 0和1 组成的数据转换成为一个十进制的数据进行存储数据库 或者 传输网络相比之下是不是 比 传递一堆的数据更小更快好像是可以的通过前面的介绍我试着找了相关的资料知晓了这种方案有个专属的名词 【位掩码】专业的定义:位掩码Bitmask是计算机科学中一种利用二进制位0 和 1来高效记录、修改和查询多个开关状态或布尔条件的技术。第02节 理解既然前面知道了 位掩码那么我们能不能更直观的从 人的角度去看待应用位掩码帮我们做事情呢为了更好的去学习 位掩码我想到了一个相对而言比较贴合的例子。现实生活中如果 您会下象棋应该知道象棋一共有 32颗 棋子。 他们分别是能否用一个 int 类型的数据来表示整个棋盘中棋子的存活呢 存在是 1 不存在是 0因为 int 类型的数据正好是 32位下面是我用 Java 代码定义的数据。为了方便于大家理解这段代码的意思我采用 xlsx 来表示内容。也就是说我们采用给个位数表示了每一颗 棋子的 存活状态。第二章 案例代码第01节 位掩码的工具类包含有 5 个方法序号方法名称方法作用举例说明1int addData(int currentMask, int targetData)添加数据参数1当前模板参数2十进制数2int removeData(int currentMask, int targetData)删除数据参数1当前模板参数2十进制数3boolean containsData(int currentMask, int targetData)判断模板中存在数据参数1当前模板参数2十进制数4ListString maskToAvailableList(int currentMask, MapString, Integer businessMap)转换 十进制 转 映射值参数1当前模板参数2映射表5String to32BitString(int number)将十进制数据转换为二进制字符串参数十进制数据代码importjava.util.ArrayList;importjava.util.List;importjava.util.Map;publicclassBitmaskUtil{/** * 1. 添加数据将某位置为 1 * 对应业务棋子入场、开启某权限、记录某数据存在 * 换算公式currentMask | targetData */publicstaticintaddData(intcurrentMask,inttargetData){returncurrentMask|targetData;}/** * 2. 剔除数据将某位置为 0 * 对应业务棋子死亡离场、关闭某权限、擦除某数据 * 换算公式currentMask ~targetData */publicstaticintremoveData(intcurrentMask,inttargetData){returncurrentMask~targetData;}/** * 3. 检查数据是否存在/存活判断某位是否为 1 * 换算公式(currentMask targetData) targetData */publicstaticbooleancontainsData(intcurrentMask,inttargetData){return(currentMasktargetData)targetData;}/** * 4. 转换数据【十进制整数 - 存活数据列表】 * 传入标准的业务字典配置表解析出当前整数里到底活着哪些数据 * * param currentMask 当前的十进制掩码 * param businessMap 业务配置字典Key为数据名称Value为位权重如 1, 2, 4, 8... */publicstaticListStringmaskToAvailableList(intcurrentMask,MapString,IntegerbusinessMap){ListStringactiveListnewArrayList();for(Map.EntryString,Integerentry:businessMap.entrySet()){if(containsData(currentMask,entry.getValue())){activeList.add(entry.getKey());}}returnactiveList;}/** * 5. 辅助工具获取精细的 32 位二进制字符串高位补0便于调试观察 */publicstaticStringto32BitString(intnumber){returnString.format(%32s,Integer.toBinaryString(number)).replace( ,0);}}第02节 映射规范类importjava.util.LinkedHashMap;importjava.util.Map;/** * 映射的规范业务规范 */publicclassSpecification{// 业务配置表publicstaticfinalMapString,IntegerconfigurationTablenewLinkedHashMap();// // 1. 黑方 16 枚棋子位定义交换后占据低 16 位即 1 0 到 1 15// // --- 底线 (九个位置) ---publicstaticfinalintB_JU_LEFT10;// 黑左车publicstaticfinalintB_MA_LEFT11;// 黑左马publicstaticfinalintB_XIANG_LEFT12;// 黑左象publicstaticfinalintB_SHI_LEFT13;// 黑左士publicstaticfinalintB_JIANG14;// 黑将 (居中无左右)publicstaticfinalintB_SHI_RIGHT15;// 黑右士publicstaticfinalintB_XIANG_RIGHT16;// 黑右象publicstaticfinalintB_MA_RIGHT17;// 黑右马publicstaticfinalintB_JU_RIGHT18;// 黑右车// --- 炮线 (两个位置) ---publicstaticfinalintB_PAO_LEFT19;// 黑左炮publicstaticfinalintB_PAO_RIGHT110;// 黑右炮// --- 卒线 (五个位置) ---publicstaticfinalintB_ZU_1111;// 黑卒1publicstaticfinalintB_ZU_2112;// 黑卒2publicstaticfinalintB_ZU_3113;// 黑卒3 (居中)publicstaticfinalintB_ZU_4114;// 黑卒4publicstaticfinalintB_ZU_5115;// 黑卒5// // 2. 红方 16 枚棋子位定义交换后占据高 16 位即 1 16 到 1 31// // --- 底线 (九个位置) ---publicstaticfinalintR_JU_LEFT116;// 红左车publicstaticfinalintR_MA_LEFT117;// 红左马publicstaticfinalintR_XIANG_LEFT118;// 红左相publicstaticfinalintR_SHI_LEFT119;// 红左仕publicstaticfinalintR_SHUAI120;// 红帅 (居中无左右)publicstaticfinalintR_SHI_RIGHT121;// 红右仕publicstaticfinalintR_XIANG_RIGHT122;// 红右相publicstaticfinalintR_MA_RIGHT123;// 红右马publicstaticfinalintR_JU_RIGHT124;// 红右车// --- 炮线 (两个位置) ---publicstaticfinalintR_PAO_LEFT125;// 红左炮publicstaticfinalintR_PAO_RIGHT126;// 红右炮// --- 兵线 (五个位置) ---publicstaticfinalintR_BING_1127;// 红兵1publicstaticfinalintR_BING_2128;// 红兵2publicstaticfinalintR_BING_3129;// 红兵3 (居中)publicstaticfinalintR_BING_4130;// 红兵4publicstaticfinalintR_BING_5131;// 红兵5static{// 填充黑方 configurationTable.put(黑左车,B_JU_LEFT);configurationTable.put(黑左马,B_MA_LEFT);configurationTable.put(黑左象,B_XIANG_LEFT);configurationTable.put(黑左士,B_SHI_LEFT);configurationTable.put(黑将,B_JIANG);configurationTable.put(黑右士,B_SHI_RIGHT);configurationTable.put(黑右象,B_XIANG_RIGHT);configurationTable.put(黑右马,B_MA_RIGHT);configurationTable.put(黑右车,B_JU_RIGHT);configurationTable.put(黑左炮,B_PAO_LEFT);configurationTable.put(黑右炮,B_PAO_RIGHT);configurationTable.put(黑卒1,B_ZU_1);configurationTable.put(黑卒2,B_ZU_2);configurationTable.put(黑卒3,B_ZU_3);configurationTable.put(黑卒4,B_ZU_4);configurationTable.put(黑卒5,B_ZU_5);// 填充红方 configurationTable.put(红左车,R_JU_LEFT);configurationTable.put(红左马,R_MA_LEFT);configurationTable.put(红左相,R_XIANG_LEFT);configurationTable.put(红左仕,R_SHI_LEFT);configurationTable.put(红帅,R_SHUAI);configurationTable.put(红右仕,R_SHI_RIGHT);configurationTable.put(红右相,R_XIANG_RIGHT);configurationTable.put(红右马,R_MA_RIGHT);configurationTable.put(红右车,R_JU_RIGHT);configurationTable.put(红左炮,R_PAO_LEFT);configurationTable.put(红右炮,R_PAO_RIGHT);configurationTable.put(红兵1,R_BING_1);configurationTable.put(红兵2,R_BING_2);configurationTable.put(红兵3,R_BING_3);configurationTable.put(红兵4,R_BING_4);configurationTable.put(红兵5,R_BING_5);}}第03节 测试类如何使用上述的几个方法呢importjava.util.List;publicclassDemo{publicstaticvoidmain(String[]args){intFULL0XFFFF_FFFF;intZERO0X0000_0000;// 在空棋盘当中, 放入了两个数据红左车 和 红帅 返回的结果是一个十进制的整数intaddDataBitmaskUtil.addData(ZERO,Specification.R_JU_LEFTSpecification.R_SHUAI);// 输出当前的十进制整数System.out.println(addData addData);// 将十进制的整数, 转换成为二进制的数据32位的0和1组成 如果存在是1, 如果不存在是 0Stringstr32addBitmaskUtil.to32BitString(addData);// 输出当前的二进制System.out.println(str32add str32add);// 将当前的数据, 转换成为映射中存在的数据值, 从映射表当中查找 存在的数据值ListStringlistAddBitmaskUtil.maskToAvailableList(addData,Specification.configurationTable);// 输出当前的映射值System.out.println(listAdd listAdd);System.out.println();// 在满棋盘当中, 移除掉数据红帅 和 红右士 返回的结果是一个十进制的整数intremoveDataBitmaskUtil.removeData(FULL,Specification.R_SHUAISpecification.R_SHI_RIGHT);// 输出当前的十进制System.out.println(removeData removeData);// 将十进制的整数, 转换成为二进制的数据32位的0和1组成 如果存在是1, 如果不存在是 0Stringstr32removeBitmaskUtil.to32BitString(removeData);// 输出当前的二进制System.out.println(str32remove str32remove);// 将当前的数据, 转换成为映射中存在的数据值, 从映射表当中查找 存在的数据值ListStringlistRemoveBitmaskUtil.maskToAvailableList(removeData,Specification.configurationTable);// 输出当前的映射值System.out.println(listRemove listRemove);// 查找当前的数据中, 是否包含有 需要查找的数据booleancontainsDataBitmaskUtil.containsData(removeData,Specification.R_SHUAI);// 输出查找的结果System.out.println(containsData containsData);}}第04节 最终输出结果addData 1114112 str32add 00000000000100010000000000000000 listAdd [红左车, 红帅] removeData -3145729 str32remove 11111111110011111111111111111111 listRemove [黑左车, 黑左马, 黑左象, 黑左士, 黑将, 黑右士, 黑右象, 黑右马, 黑右车, 黑左炮, 黑右炮, 黑卒1, 黑卒2, 黑卒3, 黑卒4, 黑卒5, 红左车, 红左马, 红左相, 红左仕, 红右相, 红右马, 红右车, 红左炮, 红右炮, 红兵1, 红兵2, 红兵3, 红兵4, 红兵5] containsData false第三章 后续操作第01节 拓展关于后续如果作为一个应用而言我们只需要1、拿着工具类 2、根据自己的业务自定义配置项应该就可以完成大部分的 实际需求。例如前面我定义的几个条件当然可能会更多。精准定位内部存储后台弹窗就可以修改配置项作为条件直接采用工具类应该是可以完成对应的 位掩码权限管理。第02节 深思方向1如果我们想要深入的理解整个操作那么可以专门去研究一下位运算的操作。 也就是关于工具类中的几个 运算符。方向2如果我没有那么多的条件选项我该如何呢 或者说我改为 16位的 short 甚至是 8位的 byte 亦或者是 64 位的 long方向3当前我写的是 Java 的版本如果我们操作的其他的语言呢 例如 C语言C等。