日常都不多用到位運算,這裏介紹一種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] }