作者:李強強
上一篇,泥瓦匠基礎地講了下Java I/O : Bit Operation 位運算。這一講,泥瓦匠帶你走進Java中的進制詳解。
一、引子
在Java世界里,99%的工作都是處理這高層。那么二進制,字節碼這些會在哪里用到呢?
自問自答:在跨平台的時候,就凸顯神功了。比如說文件讀寫,數據通信,還有Java編譯后的字節碼文件。下面會有個數據通信的例子哦。
Java對對象實現Serializablle接口,就可以將其轉化為一系列字節,而在通信中,不必要關系數據如何在不同機器表示和字節的順序。這里泥瓦匠對Serializablle接口,不做詳細講解,以后單獨詳解。
二、Java進制轉換
首先認識下Java中的數據類型:
1、Int整型:byte(8位,-128~127)、short(16位)、int(32位)、long(64位)
2、Float型:float(32位)、double(64位)
2、char字符:unicode字符(16位)
也就是說,一個int等價於長度為4的字節數組。
Java中進制如何轉換呢?
在Java中,Int整形以及char字符型被包裝的類中提供了一系列的操作方法。比如 java.lang.Integer 中,api如圖所示:
下面泥瓦匠寫個demo,驗證下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package javaBasic.oi.byteoper;
public class IntegerOper
{
public static void main(String[] args)
{
System.out.println("17的十六進制: " + Integer.toHexString(17));
System.out.println("17的八進制: " + Integer.toOctalString(17));
System.out.println("17的二進制: " + Integer.toBinaryString(17));
System.out.println(Integer.valueOf("11", 16));
System.out.println(Integer.valueOf("21", 8));
System.out.println(Integer.valueOf("00010001", 2));
}
}
|
右鍵Run一下,我們可以在控制台中看到如下輸出:
1
2
3
4
5
6
|
17的十六進制: 11
17的八進制: 21
17的二進制: 10001
17
17
17
|
補充:如果值太大,則需要調用 java.lang.Long 提供的方法。
三、Java基本類型和字節神奇轉換
這里泥瓦匠想到了自己是個學生,典型的OO思想。那學號:1206010035是整型,怎么轉成字節呢,上面說的擁有字節碼的對象能通信。所以,學校關於學號這個都是這樣的方式通信的。因此,要將學號轉成字節碼才行。
泥瓦匠就寫了個工具類 IntegerConvert.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
package javaBasic.oi.byteoper;
public class IntegerConvert
{
/**
* Int轉字節數組
*/
public static byte[] int2Bytes(int inta)
{
// 32位Int可存於長度為4的字節數組
byte[] bytes = new byte[4];
for (int i = 0; i <
bytes.length
; i++)
bytes[i] = (byte)(int)((inta >> i * 8) & 0xff);// 移位和清零
return bytes;
}
/**
* 字節數組轉Int
*/
public static int bytes2Int(byte[] bytes)
{
int inta = 0;
for (int i = 0; i < bytes.length; i++)
inta += (int)((bytes[i] & 0xff) << i * 8);// 移位和清零
return inta;
}
public static void main(String[] args)
{
// 將我的學號轉換成字節碼
byte[] bytes = IntegerConvert.int2Bytes(1206010035);
System.out.println(bytes[0] + " " + bytes[1] + " " + bytes[2] + " " + bytes[3]);
// 字節碼就可以轉換回學號
System.out.println(IntegerConvert.bytes2Int(bytes));
}
}
|
跑一下,右鍵Run,可以看到以下輸出:
1
2
|
-77 64 -30 71
1206010035
|
代碼詳細解釋如下:
1、(inta >> i * 8) & 0xff
移位 清零從左往右,按8位獲取1字節。
2、這里使用的是小端法。地位字節放在內存低地址端,即該值的起始地址。補充:32位中分大端模式(PPC)和小段端模式(x86)。
自然,Long也有其轉換方法,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public class LongConvert
{
/**
* long 轉 byte數組
*/
public static byte[] long2Bytes(long longa)
{
byte[] bytes = new byte[8];
for (int i = 0; i <
bytes.length
; i++)
bytes[i] = (byte)(long)(((longa) >> i * 8) & 0xff); // 移位和清零
return bytes;
}
/**
* byte數組 轉 long
*/
public static long bytes2Long(byte[] bytes)
{
long longa = 0;
for (int i = 0; i < bytes.length; i++)
longa += (long)((bytes[i] & 0xff) << i * 8); // 移位和清零
return longa;
}
}
|
那字符串,字符數組呢?比如泥瓦匠的名字:李強強
Java也提供了一系列的方法,其實 java.lang.String 封裝了char[],其中本質還是對char數組的操作。代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package javaBasic.oi.byteoper;
public class StringConvert
{
public static void main(String[] args)
{
String str = "李強強";
byte[] bytes = str.getBytes();
// 打印字節數組
System.out.println("'李強強'的字節數組為:");
for (int i = 0; i < bytes.length; i++)
System.out.print("\t" + bytes[i]);
}
}
|
右鍵Run一下,可以看到以下輸出:
1
2
|
'李強強'的字節數組為:
-64 -18 -57 -65 -57 -65
|
論證:這里我們論證了一個中文,需要兩個字節表示,也就是說一個中文是16位。
四、淺談Java通信中的數據
如圖,庫表中一個學生對象,有個屬性是學號。這時候客戶端要向服務端發送這個對象。過程如下:
1、對象實現Serializable接口。
實現了Serializable接口的對象,可將它們轉換成一系列字節,並可在以后完全恢復回原來的樣子。
2、其學號屬性值 1206010035,由客戶端轉換為字節碼。
3、字節碼傳輸至服務端
4、服務端接收並轉換為對象屬性值。
五、總結
此文講的點有點多,泥瓦匠就想把這塊用到的知識點串起來,然后慢慢每個講解。總結如下:
1、Java中進制轉換是什么?
2、Java中進制轉換的作用?
Writer :BYSocket(泥沙磚瓦漿木匠)
微 博:BYSocket
豆 瓣:BYSocket
FaceBook:BYSocket
Twitter :BYSocket