Java位运算符总结

来源:互联网 发布:美工算平面设计吗 编辑:程序博客网 时间:2024/05/16 15:24

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);// 结果是129

下面分析-127&0xFF的过程

  1. -127的补码表示(10000001)

  2. JVM向控制台输出时,检测到byte向int类型的转换于是做了一个补位处理
    (10000001) -> (11111111,11111111,11111111,10000001)
    这个32位的补码表示也是-127, 此时转换过后的二进制数据的十进制表示仍然是相同的,但是此时补码的因为高位补1已经不一致了,我们为了保证补码的一致性,必须进行&0xFF操作.

  3. 进行&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个单位存储,需要分四次写入

// 将int数据写到硬盘上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();    } // 同样也是分四次读,每次获取8位数据,然后读四次 // 从文件中读取int类型的值 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类型的序列化

 // long类型在JVM运行时占用8个字节,也就是64位,所以我们需要分8次向文件中写入数据 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();    }    // 同样, 分8次从文件中读取数据,记得 &0xFFL 转换成long类型    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{        // 如果是long类型,那么数字结尾处必须加上L,否则会认为是int类型        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();        /*         * 结果:         * 序列化前: -538379527         * 序列化后: -538379527         * 序列化前: -2312322461839328519         * 序列化后: -2312322461839328519         */    }    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{        // 如果是long类型,那么数字结尾处必须加上L,否则会认为是int类型        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();            }        }    }}
0 0
原创粉丝点击