Java中的位操作符
&(与)操作
两个操作数中位都为1,结果才为1,否则结果为0
public class data13
{
public static void main(String[] args)
{
int a=
129;
int b=
128;
System.
out.println(
"a 和b 与的结果是:"+(a&b));
}
}
运行结果: a 和b 与的结果是:128 下面分析这个程序: “a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。
|(或)运算符
或运算符用符号“|”表示,其运算规律如下: 两个位只要有一个为1,那么结果就是1,否则就为0,下面看一个简单的例子。
public class data14
{
public static void main(String[] args)
{
int a=
129;
int b=
128;
System.
out.println(
"a 和b 或的结果是:"+(a|b));
}
}
运行结果 a 和b 或的结果是:129 下面分析这个程序段: a 的值是129,转换成二进制就是10000001,而b 的值是128,转换成二进制就是10000000,根据或运算符的运算规律,只有两个位有一个是1,结果才是1,可以知道结果就是10000001,即129。
^(异或)运算符
异或运算符是用符号“^”表示的,其运算规律是: 两个操作数的位中,相同则结果为0,不同则结果为1。下面看一个简单的例子。
public class data16
{
public static void main(String[] args)
{
int a=
15;
int b=
2;
System.
out.println(
"a 与 b 异或的结果是:"+(a^b));
}
}
运行结果 a 与 b 异或的结果是:13 分析上面的程序段:a 的值是15,转换成二进制为1111,而b 的值是2,转换成二进制为0010,根据异或的运算规律,可以得出其结果为1101 即13。
~(非)运算符
非运算符用符号“~”表示,其运算规律如下:
如果位为0,结果是1,如果位为1,结果是0,下面看一个简单例子。
public class data15
{
public static void main(String[] args)
{
int a=
2;
System.
out.println(
"a 非的结果是:"+(~a));
}
}
运行结果是: -3, 2的二进制表示是:0000….000010 然后取~, 结果是1111….111101, 将补码转换成十进制就是-3
<< (左移)运算符
<< 和>>为数值位移,>>>为逻辑位移。【注】:Java中不存在<<<。 m<<n的含义:把整数m表示的二进制数左移n位,高位移出n位都舍弃,低位补0. (此时将会出现正数变成负数的形式)
3<<2剖析:
3的二进制形式: 00000000 00000000 00000000 00000011,按照左移的原理,得到00000000 00000000 00000000 00001100,即为12. 左移使整数变为负数:
10737418<<8
10737418二进制表示形式:00000000 10100011 11010111 00001010,按照左移的原理,得到10100011 11010111 00001010 00000000,即为:-1546188288.
>>(逻辑右移)运算符
m>>n的含义:把整数m表示的二进制数右移n位,m为正数,高位全部补0;m为负数,高位全部补1. >> 会根据符号位的正负进行补位
3>>2剖析:
3二进制形式: 00000000 00000000 00000000 00000011,按照右移的原理,得到00000000 00000000 00000000 00000000,即为0. -3>>2剖析: -3二进制形式: 11111111 11111111 11111111 11111101,按照右移的原理,得到11111111 11111111 11111111 11111111,即为-1.
以上:每 个整数表示的二进制都是32位的,如果右移32位和右移0位的效果是一样的。依次类推,右移32的倍数位都一样。
>>>(无符号右移)运算符
m>>>n:整数m表示的二进制右移n位,不论正负数,高位都补零。
3>>>2剖析:
3二进制形式: 00000000 00000000 00000000 00000011,按照无符号右移的原理,得到00000000 00000000 00000000 00000000,即为0. -3>>>2剖析: -3二进制形式: 11111111 11111111 11111111 11111101,按照无符号右移的原理,得到00111111 11111111 11111111 11111111,即为1073741823.
&0xFF的意义
byte类型转换成int类型时需要进行 &0xFF的操作, 原因跟计算机的存储原理有关。
数据在内存是以补码的形式存在的。 补码: 正数(000000001): 正数的补码和反码都是它本身。 负数(100000001): 反码是对原码除了符号位之外作取反运算即(111111110),补码是对反码作+1运算即(111111111)。
System.
out.println(-
127 &
0xFF);
下面分析-127&0xFF的过程
-127的补码表示(10000001)
JVM向控制台输出时,检测到byte向int类型的转换于是做了一个补位处理 (10000001) -> (11111111,11111111,11111111,10000001) 这个32位的补码表示也是-127, 此时转换过后的二进制数据的十进制表示仍然是相同的,但是此时补码的因为高位补1已经不一致了,我们为了保证补码的一致性,必须进行&0xFF操作.
进行&0xFF操作 &0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。 当然,保证了二进制数据性的同时,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化。 比如-127&0xff; -127 & 0xff=(11111111,11111111,111111111,10000001) & (00000000,00000000,00000000,11111111) = (00000000,00000000,00000000,10000001) 这个值算一下就是129.
// &
0xFF 的区别
System
.out.println(Integer
.toBinaryString(-
127))
System
.out.println(Integer
.toBinaryString(-
127 &
0xFF))
//
11111111111111111111111110000001
//
10000001
Java实现int和long类型的序列化
简单对上面的知识进行一个总结 这个小demo就是将int和long类型的数值写到文件中,然后在读出来,如果结果正确证明序列化成功.
创建文件
private static void createFile() {
sFile =
new File(
"./",
"obj");
sFile.delete();
if (!sFile.exists()) {
try {
sFile.createNewFile();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
int类型的序列化
int类型占8个字节,每次右移8个单位存储,需要分四次写入
private static void writeInt(
int num)
throws IOException {
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream(sFile));
bos.write((num >>
0) &
0xFF);
bos.write((num >>
8) &
0xFF);
bos.write((num >>
16) &
0xFF);
bos.write((num >>
24) &
0xFF);
bos.flush();
bos.close();
}
private static int readInt()
throws IOException {
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream(sFile));
int num =
0;
num |= bis.read();
num |= bis.read() <<
8;
num |= bis.read() <<
16;
num |= bis.read() <<
24;
bis.close();
return num;
}
long类型的序列化
private static void writeLong(
long num)
throws IOException {
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream(sFile));
bos.write((
int) ((num >>
0) &
0xFFL));
bos.write((
int) ((num >>
8) &
0xFFL));
bos.write((
int) ((num >>
16) &
0xFFL));
bos.write((
int) ((num >>
24) &
0xFFL));
bos.write((
int) ((num >>
32) &
0xFFL));
bos.write((
int) ((num >>
40) &
0xFFL));
bos.write((
int) ((num >>
48) &
0xFFL));
bos.write((
int) ((num >>
56) &
0xFFL));
bos.flush();
bos.close();
}
private static long readLong()
throws IOException {
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream(sFile));
long num =
0L;
num |= (bis.read() &
0xFFL) <<
0;
num |= (bis.read() &
0xFFL) <<
8;
num |= (bis.read() &
0xFFL) <<
16;
num |= (bis.read() &
0xFFL) <<
24;
num |= (bis.read() &
0xFFL) <<
32;
num |= (bis.read() &
0xFFL) <<
40;
num |= (bis.read() &
0xFFL) <<
48;
num |= (bis.read() &
0xFFL) <<
56;
bis.close();
return num;
}
测试代码
private static void serialIntTest() throws IOException {
final
int magic = -
0x20170507;
System.
out.println(
"序列化前: " + magic);
writeInt(magic);
System.
out.println(
"序列化后: " + readInt());
}
private static void serialLongTest() throws IOException{
final
long magicLong = -
0x2017050720170507L;
System.
out.println(
"序列化前: " + magicLong);
writeLong(magicLong);
System.
out.println(
"序列化后: " + readLong());
}
完整代码
/**
* Created by yangtianrui on 17-5-7.
*/
public class WriteByteToFile {
private static File sFile;
public static void main(String[] args)
throws Exception {
createFile();
serialIntTest();
serialLongTest();
}
private static void serialIntTest()
throws IOException {
final int magic = -
0x20170507;
System.out.println(
"序列化前: " + magic);
writeInt(magic);
System.out.println(
"序列化后: " + readInt());
}
private static void serialLongTest()
throws IOException{
final long magicLong = -
0x2017050720170507L;
System.out.println(
"序列化前: " + magicLong);
writeLong(magicLong);
System.out.println(
"序列化后: " + readLong());
}
private static void writeInt(
int num)
throws IOException {
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream(sFile));
bos.write((num >>
0) &
0xFF);
bos.write((num >>
8) &
0xFF);
bos.write((num >>
16) &
0xFF);
bos.write((num >>
24) &
0xFF);
bos.flush();
bos.close();
}
private static int readInt()
throws IOException {
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream(sFile));
int num =
0;
num |= bis.read();
num |= bis.read() <<
8;
num |= bis.read() <<
16;
num |= bis.read() <<
24;
bis.close();
return num;
}
private static void writeLong(
long num)
throws IOException {
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream(sFile));
bos.write((
int) ((num >>
0) &
0xFFL));
bos.write((
int) ((num >>
8) &
0xFFL));
bos.write((
int) ((num >>
16) &
0xFFL));
bos.write((
int) ((num >>
24) &
0xFFL));
bos.write((
int) ((num >>
32) &
0xFFL));
bos.write((
int) ((num >>
40) &
0xFFL));
bos.write((
int) ((num >>
48) &
0xFFL));
bos.write((
int) ((num >>
56) &
0xFFL));
bos.flush();
bos.close();
}
private static long readLong()
throws IOException {
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream(sFile));
long num =
0L;
num |= (bis.read() &
0xFFL) <<
0;
num |= (bis.read() &
0xFFL) <<
8;
num |= (bis.read() &
0xFFL) <<
16;
num |= (bis.read() &
0xFFL) <<
24;
num |= (bis.read() &
0xFFL) <<
32;
num |= (bis.read() &
0xFFL) <<
40;
num |= (bis.read() &
0xFFL) <<
48;
num |= (bis.read() &
0xFFL) <<
56;
bis.close();
return num;
}
private static void createFile() {
sFile =
new File(
"./",
"obj");
sFile.delete();
if (!sFile.exists()) {
try {
sFile.createNewFile();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}