問題
在 Java 中,如何使用一個 byte 類型的變量保存多個 boolean 類型的值世吨?
場景
請選擇喜愛的球類運動(多選):
□ 足球 | □ 籃球 | □ 乒乓球 |
---|---|---|
□ 臺球 | □ 排球 | □ 羽毛球 |
在如上所描述的場景中谎砾,如何使用一個 byte 類型的變量來保存各項是否選中?
回答
常規(guī)思路是定義 6 個 boolean 類型的變量埂奈,每個變量保存一項的狀態(tài), 選中為 true
, 否則為 false
戳吝。
boolean footballIsChecked = false;
...
boolean badmintonIsChecked = false;
在 Java 中,byte 類型的數(shù)據(jù)使用 8 位進行保存,每一位的值可能是 0
或 1
兜看。理論上來講锥咸,byte 類型存儲空間的每一位可以表示一個 boolean 類型的值,1
表示 true
细移,0
表示 false
搏予。
byte sportCheckedState;
sportCheckedState = 0b0000_0000; //都沒選中
sportCheckedState = 0b0000_0001; //選中了足球
sportCheckedState = 0b0000_0010; //選中了籃球
因此,我們的需要解決問題變成了如何將 byte 類型某一位存儲空間的值設(shè)置為 0
或 1
, 如何讀取某一位的值弧轧。
設(shè)置 byte 類型某一位的存儲空間的值
如何將某一位的值設(shè)置為 0
呢雪侥?
0 & 0 = 0
0 & 1 = 0
答:該位和 0
進行 &
運算。
如何將某一位的值設(shè)置為 1
呢精绎?
1 | 0 = 1
1 | 1 = 1
答:該位和 1
進行 |
運算速缨。
既然是設(shè)置某一位的值,就應(yīng)該不影響其他位的值代乃。
執(zhí)行 &
運算時旬牲,如何讓運算結(jié)果和運算數(shù)相等?
1 & 0 = 0
1 & 1 = 1
答:當(dāng)另外一個運算數(shù)為 1
時搁吓,運算結(jié)果和此運算數(shù)相同原茅。
執(zhí)行 |
運算時,如何讓運算結(jié)果和運算數(shù)相等堕仔?
0 | 0 = 0
0 | 1 = 1
答:當(dāng)另外一個運算數(shù)為 0
時擂橘,運算結(jié)果和此運算數(shù)相同。
綜上摩骨,設(shè)置某一位為 0
時通贞,進行 &
運算,輔助運算數(shù)(另外一個參與運算的數(shù))應(yīng)該符合這樣的規(guī)則:目標(biāo)位為0
, 其他位為 1
恼五。 例如設(shè)置最后一位昌罩,輔助運算數(shù)為 1111_1110
;
1 0 1 0
& 1 1 1 0 //輔助運算數(shù)
----------
1 0 1 0 //運算結(jié)果的前 3 位不變唤冈,最后一位設(shè)置為 0
1 0 1 1
& 1 1 1 0 //輔助運算數(shù)
----------
1 0 1 0 //運算結(jié)果的前 3 位不變峡迷,最后一位設(shè)置為 0
設(shè)置某一位為1
時,進行 |
運算你虹,輔助運算數(shù)應(yīng)該符合這樣的規(guī)則:目標(biāo)位為 1
, 其它位為 0
。例如設(shè)置最后一位彤避,輔助運算數(shù)為 0000_0001
傅物。
1 0 1 0
| 0 0 0 1 //輔助運算數(shù)
----------
1 0 1 1 //運算結(jié)果的前 3 位不變,最后一位設(shè)置為 1
1 0 1 1
| 0 0 0 1 //輔助運算數(shù)
----------
1 0 1 1 //運算結(jié)果的前 3 位不變琉预,最后一位設(shè)置為 1
讀取 byte 類型某一位的存儲空間的值
和 1
進行 &
時董饰,運算結(jié)果和另外一個運算數(shù)相同。
1 & 0 = 0
1 & 1 = 1
和 0
進行 &
時,運算結(jié)果為0
卒暂。
0 & 0 = 0
0 & 1 = 0
為了方便啄栓,我們希望 &
運算結(jié)果的其他位為 0
,根據(jù) 0000_0000
的運算結(jié)果可以推算出目標(biāo)位的值為 0
也祠;根據(jù)目標(biāo)位為 1
昙楚,其它位的值為 0
的運算結(jié)果可以推算出目標(biāo)位的值為 1
。
所以诈嘿,構(gòu)造出的輔助運算數(shù)應(yīng)該符合這樣的規(guī)則:目標(biāo)位的值為 1
堪旧,其他位的值為 0
。例如奖亚,倒數(shù)第二位應(yīng)該選取的輔助運算數(shù)為 0000_0010
淳梦。
1 0 1 0
& 0 0 1 0 //輔助運算數(shù)
----------
0 0 1 0 //運算結(jié)果的 1、2昔字、4 位置為 0爆袍,第 3 為值為 1 ,即運算數(shù)第 3 位值為 1
1 0 0 0
& 0 0 1 0 //輔助運算數(shù)
----------
0 0 0 0 //運算結(jié)果的 1作郭、2螃宙、4 位置為 0,第 3 為值為 0 所坯,即運算數(shù)第 3 位值為 0
據(jù)此谆扎,我們可以得出結(jié)論:運算結(jié)果每一位的值都是 0
時,目標(biāo)位的值為 0
芹助;運算結(jié)果存在值不為 0
的位時堂湖,目標(biāo)位的值為 1
。
示例
// 每個狀態(tài)用一位表示状土,1 選中无蜂, 0 未選中
private static final byte CHECKED_FOOTBALL = 0b0000_0001;
private byte state = STATE_VALUE_DEFAULT;
public void setFootballCheckedState(boolean isChecked) {
if (isChecked) {
state = (byte) (state | CHECKED_FOOTBALL);
} else {
state = (byte) (state & ~CHECKED_FOOTBALL);
}
}
public boolean footballIsChecked() {
return (state & CHECKED_FOOTBALL) == CHECKED_FOOTBALL;
}