深入探究JAVA底层技术实现


概述

本文主要介绍java的二进制处理和相关的底层基础问题探索

JAVA的基础数据类型8种

类型 位数 字节数 范围
byte 8位 1字节 -128(-2^7) — 127(2^7 - 1
short 16位 2字节 -32768(-2^15)— 32767(2^15 - 1)
int 32位 4字节 -2,147,483,648(-2^31) — -2,147,483,647(2^31 - 1)
long 64位 8字节 默认值0L
float 32位 4字节 默认值0.0f
double 64位 8字节 默认值0.0d
boolean 1位 默认值false
char 16位 2字节 Unicode字符 \u0000(0) — \uffff(65535)

位运算运算符

类型 计算方式 速记方式
& 10101010 & 01010101 = 00000000 有0为0,出现0则为0
| 10101010 | 01010101 = 11111111 有1为1,出现1则为1
^ 10101010 ^ 01010101 = 11111111 合2为1,出现不同则为1,相同则为0
~ ~10101010 = 0101010101 1变为0,0变为1
<< 10101010 << 0xFF 左移0xFF位,右补0相当与*2
>> 10101010 >> 0xFF 有符号右移0xFF位,正数高位补0,负数补1
>>> 10101010 >>> 0xFF 无符号右移0xFF位,高位全部补0

基础类型说明

从上面我们可以发现JAVA和C的差异,C语言整数默认是signed有符号的,C语言中也可用unsigned 表示一个无符号值,JAVA整数都是有符号的,但也可通过一些方式表示无符号值。

如何用JAVA表示C语言的正确值

java提供了一种方式来表示 C的 unsigned int short等, 如何实现,对当前的数据进行&运算,和谁?
具体和谁需要看你的数据类型,0xff的二进制是1111 1111 (8bit)

    public int getUnsignedByte (byte data){ //将data字节型数据转换为0~255 (0xFF 即BYTE),
        return data & 0x0FF ; //int 4字节 32位 表示将高24位全部变为0,保留低8位原始值,变为有符号首位为0的值,相当于C的有符号值
    } 
    public int getUnsignedByte (short data){ //将data字节型数据转换为0~65535 (0xFFFF 即WORD)。 
        return data & 0x0FFFF ; //int 4字节 32位 表示将高16位全部变为0,保留低16位原始值,变为有符号首位为0的值,相当于C的有符号值
    } 
    public long getUnsignedIntt (int data){ //将int数据转换为0~4294967295 (0xFFFFFFFF即DWORD)。 
        return data & 0x0FFFFFFFF ; //long 8字节 64位 表示将高32位全部变为0,保留低32位原始值,变为有符号首位为0的值,相当于C的有符号值
    }

负数的二进制

在计算机中,正数是以原码的形式存储的,而负数是以补码的形式存储的,负数的二进制需要该数正数按位取反的值再+1.

详解>>>预算符

负数int -20无符号右移:r = -20 >>> 2

注:数据类型默认为int 32位

    -20://负数的二进制需要该数正数按位取反的值再+1.
    源码:10000000  00000000   00000000   00010100
    
    反码:11111111  11111111   11111111   11101011//反码后+1
    
    补码:11111111  11111111   11111111   11101100 
    
    右移:00111111  11111111   11111111   11111011
    
    结果:r = 1073741819

^交换 a b 值

        a=a∧b;
        b=b∧a;
        c=a∧b;

大端模式和小端模式

  1. 大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    > 低地址 ——————–\> 高地址  
    > 0x12 | 0x34 | 0x56 | 0x78
    
  2. 小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

    > 低地址 ——————–\> 高地址  
    > 0x78 | 0x56 | 0x34 | 0x12
    
  3. 常见的CPU字节序

    > Big Endian : PowerPC、IBM、Sun  
    > Little Endian : x86、DEC  
    > ARM既可以工作在大端模式,也可以工作在小端模式  
    > JAVA和大部分的网络通讯协议都是使用Big-Endian的编码.
    
  4. 常见文件的字节序

    > Adobe PS – Big Endian  
    > BMP – Little Endian  
    > DXF(AutoCAD) – Variable  
    > GIF – Little Endian  
    > JPEG – Big Endian  
    > MacPaint – Big Endian  
    > RTF – Little Endian
    
  5. 读取存储数据的顺序

    不管是大端还是小端模式,我们在读取和存储数据的时候一定都是从内存的低地址依次向高地址读取或写入。[ps这句话非常重要,请注意理解]

A内存地址 A存储的值
0x2000 4001 0x01
0x2000 4002 0x02
0x2000 4003 0x03
0x2000 4004 0x04
> 如果现在大端模式A传递此数据给B小端模式  
> A将**内存**中的值取出,取值由**内存**的低地址往高地址取值,由于大端模式的**内存**低位地址(即0X01)对应字节数组高位值,则字节数组最高位(最左边位)为\[0x01,X,X,X\],则传递值为0x1234。
> B接收到字节数组在**内存中**存储的时候也是按照内存低地址往高地址开始依次存储,由于小端模式的**内存**低位地址(即0x04)对应字节数组低位值,则在B中内存存储的数据为:
B内存地址 B存储的值
0x8000 4001 0x04
0x8000 4002 0x03
0x8000 4003 0x02
0x8000 4004 0x01
> B将**内存**中的值取出,取值由**内存**的低地址往高地址取值,
则字节数组最低位(最右边位)为\[X,X,X,0x1\],则取出值为0x4321.
> 为什么在内存中同样的存储,取到的值不一样呢,因为此数组是4个字节,
按照小端模式取出来的值则不一样,如果字节序一样则值相同,
如果只是单字节,也是相同的,不需要关心顺序。
> 会发现数据由A传递给B后其显示的数据发生了翻天覆地的变化,
这就是为啥在处理网络数据的时候要确定字节序的原因,
必须保证A和B的字节序相同,如果不同,就需要使用字节序的转换函数。

如何理解JAVA的有符号 [1byte -128 - 127]

举个栗子:

JAVA的一个byte8位表示为10000001, C语言的一个byte8位表示为10000001  
> 这个byte在JAVA和C中代表了不同的值JAVA > -1 C > -129为什么?  
> 因为JAVA作为有符号其左边第一位用来表示正负值,第一位为1表示为一个负数,其表示的实际值为-1,而C语言左边第一位仍然表示数值其值为2^7 + 1 = 129 ,java 则为-1.

异或加密和解密

      /**
         * xor 加密 key=xxxxxxxxxx
        * @Description:
        * @param data
        * @return
         */
        public  byte[] xorEncode(byte[] data){  
    
             for(int i = 0; i < data.length; ++i){  
                 data[i] ^= keyBytes[i%keyBytes.length];  
             }  
    
             return data;  
    
        }  
    
    
        /**
         * xor 解密 key=1234567890
        * @Description:
        * @param data
        * @return
         */
        public  byte[] xorDecode(byte[] data){
    
            for(int i = 0; i < data.length; ++i){  
                data[i] ^= keyBytes[i%keyBytes.length];  
            }  
            return data;
        }

JAVA byte[] TO short 的大小端和无符号相互转换

        /** 
         * @功能 字节的转换与短整型  小端模式
         * @param 两位的字节数组 
         * @return 短整型 
         */  
        public  short byteToShort(byte[] b) {  
            short s = 0;  
            short s0 = (short) (b[0] & 0xff);// 最低位  
            short s1 = (short) (b[1] & 0xff);  
            s1 <<= 8;  //byte数组低位值左移8位
            s = (short) (s0 | s1);  
            return s;  
        }  
    
        /** 
         * @功能 字节的转换与短整型  大端模式
         * @param 两位的字节数组 
         * @return 短整型 
         */  
        public  short byteToShort_BIG(byte[] b) {  
            short s = 0;  
            short s0 = (short) (b[1] & 0
QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空