日常都不多用到位运算,这里介绍一种jdk
使用位运算的小案例。它是用位运算来优化一个类所占的大小。下面介绍:html
假设一个类须要有不少boolean
类型得属性,若是直接用boolean
类型,那么这个类会在内存中占用很大空间。一般状况下,一个boolean
类型属性会占4个字节。但这不是必定得,JAVA得boolean属性占用字节不必定。这时候,使用多个boolean
类型的属性就占用不少内存。java
在这种状况下,可使用字节得0、1来表明true、false。使用位运算来获取、设置boolean属性得值。好比说:咱们可使用int
来存储32个boolean属性,这样就会节省大量的内存。优化
JDK
中有具体得例子,如java.lang.reflect.Modifier
code
假设一个猫有三个属性:cute
、fat
、white
,其取值只有俩种true、false。如今用int的后面三个位来存储这三个类型的值。
即:在int
最后一个位做为cute
属性得值;倒数第二位做为fat
属性得值;倒数第三位做为white
属性得值。htm
一、建立int
属性得值,做为存储这三个属性得属性值blog
public class Cat { // 存储三个boolean属性得值 private int properties = 0; }
二、设置三个int
属性做为三个属性都为true;这是为了后期方便设置值内存
public class Cat { private static int CUTE = 0x1; private static int FAT = 0x2; private static int WHITE = 0x4; private int properties = 0; }
三、以cute
属性的获取、设置
(1)获取值的时候
指获取properties
属性的最后一位的值,须要注意的是获取最后一位值得时候,不能影响其余位得值!!!get
/** * 这只猫萌吗?请在此处使用位运算读取properties,获得猫是否萌的结果 * * @return 萌则返回true,不然返回false */ public boolean isCute() { return (properties & Cat.CUTE) != 0; }
使用与运算得时候,其余位不受影响;最后一位也是取决于
properties
最后一位得值
it
(2)设置值的时候
在设置properties
属性得最后一位得值,须要注意得是设置最后一位的值的时候,不能影响其余位得值!!!class
/** * 使用位运算设置猫咪萌的属性 * * @param cute true为萌,false为不萌 */ public void setCute(boolean cute) { if (cute == true){ properties = properties | Cat.CUTE; } else { properties = properties & (~Cat.CUTE); } }
四、设置其余属性
/** * 使用位运算设置猫咪胖的属性 * * @param fat true为胖,false为不胖 */ public void setFat(boolean fat) { if (fat){ properties = properties | Cat.FAT; } else { properties = properties & (~Cat.FAT); } } /** * 这只猫胖吗?请在此处使用位运算读取properties,获得猫是否胖的结果 * * @return 胖则返回true,不然返回false */ public boolean isFat() { return (properties & Cat.FAT) != 0; } /** * 使用位运算设置猫咪白的属性 * * @param white true为白,false为不白 */ public void setWhite(boolean white) { if (white){ properties = properties | Cat.WHITE; } else { properties = properties & (~Cat.WHITE); } } /** * 这只猫白吗?请在此处使用位运算读取properties,获得猫是否白的结果 * * @return 白则返回true,不然返回false */ public boolean isWhite() { return (properties & Cat.WHITE) != 0; }
通常状况下,获取值使用&
;设置值使用|
、~
和&
。关键就是在使用位运算的时候,只影响指定位置的值,其余位置的值不能改变。完整代码以下:
public class Cat { private static int CUTE = 0x1; private static int FAT = 0x2; private static int WHITE = 0x4; private int properties = 0; /** * 使用位运算设置猫咪萌的属性 * * @param cute true为萌,false为不萌 */ public void setCute(boolean cute) { if (cute == true){ properties = properties | Cat.CUTE; } else { properties = properties & (~Cat.CUTE); } } /** * 这只猫萌吗?请在此处使用位运算读取properties,获得猫是否萌的结果 * * @return 萌则返回true,不然返回false */ public boolean isCute() { return (properties & Cat.CUTE) != 0; } /** * 使用位运算设置猫咪胖的属性 * * @param fat true为胖,false为不胖 */ public void setFat(boolean fat) { if (fat){ properties = properties | Cat.FAT; } else { properties = properties & (~Cat.FAT); } } /** * 这只猫胖吗?请在此处使用位运算读取properties,获得猫是否胖的结果 * * @return 胖则返回true,不然返回false */ public boolean isFat() { return (properties & Cat.FAT) != 0; } /** * 使用位运算设置猫咪白的属性 * * @param white true为白,false为不白 */ public void setWhite(boolean white) { if (white){ properties = properties | Cat.WHITE; } else { properties = properties & (~Cat.WHITE); } } /** * 这只猫白吗?请在此处使用位运算读取properties,获得猫是否白的结果 * * @return 白则返回true,不然返回false */ public boolean isWhite() { return (properties & Cat.WHITE) != 0; } public static void main(String[] args) { Cat cat = new Cat(); cat.setCute(true); cat.setFat(true); cat.setWhite(false); System.out.println("这只猫萌吗:" + cat.isCute()); System.out.println("这只猫胖吗:" + cat.isFat()); System.out.println("这只猫白吗:" + cat.isWhite()); } }
交换俩个值得功能能够用位运算这种骚操做完成。好比:
public static void main(String[] args) { Main main = new Main(); int[] arr = {1,2}; main.test(0,1,arr); } public void test(int a, int b, int[] arr){ arr[a] = arr[a] ^ arr[b]; arr[b] = arr[a] ^ arr[b]; arr[a] = arr[a] ^ arr[b]; System.out.println(Arrays.toString(arr));//[2,1] }
但这里有个坑,若是你传得俩个地址是同样得话,就会出错:
public static void main(String[] args) { Main main = new Main(); int[] arr = {1,2}; main.test(0,0,arr); } public void test(int a, int b, int[] arr){ arr[a] = arr[a] ^ arr[b]; arr[b] = arr[a] ^ arr[b]; arr[a] = arr[a] ^ arr[b]; System.out.println(Arrays.toString(arr));//[0,1] }