Android/Kotlin資料操作byte16進位制0xaa變為0xffffffaa的解決辦法
解決辦法
#kotlin
Integer.toHexString(itm.toInt() and(0xff))
#java
Integer.toHexString(itm.toInt() & 0xff)
以下為引用內容,方便查閱
引自https://www.cnblogs.com/cvbaka/archive/2004/01/13/4747337.html
這是因為Integer.toHexString()的接收引數是int,不是byte,於是運算是會先把byte強制轉換為int
由於java中強制轉換是保持值不變,而在計算機中數都是用補碼錶示的,java中int是32位4個byte, 正數補碼是正數本身,這樣不會有問題,強轉為32位時前面24位會填充0,
而負數的補碼是"將其對應正數二進位制表示所有位取反(包括符號位,0變1,1變0)後加1",
於是32位的0x00 00 00 80(0000 ... 0000 1000 0000)補碼是0xFF FF FF 80(1111 ... 1111 1000 0000),前面是填充的1
所以Integer.toHexString()後就會變成前面多了一串F
引自https://blog.csdn.net/Jamie_Jiang/article/details/78343549?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
今天學到一句Integer.toHexString(b & 0xff)(b是byte型別的)
馬克一下什麼意思
Integer.toHexString這個方法是把位元組(轉換成了int)以16進位制的方式顯示。
首先,
以下是java.lang.Integer.toHexString()方法的宣告
public static String toHexString(int i)
其次,
&是什麼
&是位操作符,“按位與”當&作為位運算時,1&1=1 ,1&0=0,0&0=0
舉個栗子: a=1;b=2;a&b=0
計算方法為:
1轉成二進位制 01
2轉成二進位制 10
所以,a&b=00 轉成十進位制為0
然後,
0xff是什麼
0x表示是十六進位制。
ff是兩個十六進位制的數,每個f用二進位制表示是1111,所以佔四位(bit),兩個f(ff)佔八位(bit),八位(bit)也就是一個位元組(byte).
最後,
上面的這些都理解了,那麼具體是怎麼個流程呢?
首先toHexString傳的引數應該是int型別32位,此處傳的是byte型別8位,所以前面需要補24個0。然後& 0xff 就是把前面24個0去掉只要後8位。
(經過百度)int本身就是由4組byte組成,並且Java中本身就以byte讀取。所以此處傳參沒有問題。
toHexString(b & 0xff)相當於做了一次位的與運算,將前24位字元省略,將後8位保留。即只轉了後8位。即可得到兩個十六進位制的值。
我的理解是這樣,如有不對歡迎指正!也可補充!
引自https://blog.csdn.net/u010428110/article/details/106824749/
一、位操作:
shl(bits) – 左移位 (Java’s <<)
shr(bits) – 右移位 (Java’s >>)
ushr(bits) – 無符號右移位 (Java’s >>>)
and(bits) – 與 &
or(bits) – 或 ||
xor(bits) – 異或
inv() – 反向
val a = 5
val b = a shl 2 //左移2位,5*2*2=20
println(b) //20
二、位運算子:
運算子 表示含義
and(bits) 按位與
or(bits) 按位或
inv(bits) 按位非
xor(bits) 按位異或
shl(bits) 左移運算子
shr(bits) 右移運算子
ushr(bits) 無符號右移運算子
三、Kotlin的位運算子只能對Int和Long兩種資料型別起作用。
四、位操作和位運算例項
通過位運算來保證頭尾不超過陣列範圍,通過位操作來擴容(陣列長度保持為2的整數倍,方便進行位運算)
//如ArrayDeque通過位與運算(等價於java中的'&'),保證頭尾不超過陣列邊界
class SimpleIntArrayDeque {
private var elements: Array<Int?> = arrayOfNulls(16) //擴容陣列
private var head: Int = 0 //頭
private var tail: Int = elements.size //尾,tail-1是當前最後一位資料
fun addFirst(value: Int) {
if (value == null)
throw NullPointerException()
//當head-1為-1時,實際上是11111111&00111111,結果是00111111,也就是物理陣列的尾部15;
head = (head - 1) and (elements.size - 1)
elements[head] = value
if (head == tail)
doubleCapacity()
}
fun addLast(value: Int) {
if (value == null)
throw NullPointerException()
elements[tail] = value
//當tail+1為16時,實際上是01000000&00111111,結果是00000000,也就是物理陣列的頭部0;
tail = (tail + 1) and (elements.size - 1)
if (tail == head)
doubleCapacity()
}
fun pollFirst(): Int? {
val h = head
val result = elements[h]
if (result != null) {
elements[h] = null
head = (h + 1) and (elements.size - 1)
}
return result
}
fun pollLast(): Int? {
val t = (tail - 1) and (elements.size - 1)
val result = elements[t]
if (result != null) {
elements[t] = null
tail = t
}
return result
}
//擴容:插入資料前,判斷插入後將頭尾相等(即插入後陣列將填滿),則立即擴容
private fun doubleCapacity() {
val p = head
val n = elements.size
val r = n - p
var newCapacity = n shl 1 //擴容2倍
if (newCapacity < 0)
throw IllegalArgumentException("Sorry, deque too big")
var newElements: Array<Int?> = arrayOfNulls(newCapacity)
//從頭部開始拷貝,拷貝頭部以後的所有內容,並把頭部位置重置為0
System.arraycopy(elements, p, newElements, 0, r)
/**
* 從0開始拷貝,拷貝頭部之前的內容,並把拷貝內容接上剛才拷貝的位置,
* 使得原來的陣列放到新陣列的前半部分
*/
System.arraycopy(elements, 0, newElements, r, p)
//釋放舊的陣列記憶體
Arrays.fill(elements, null)
elements = newElements
head = 0
tail = n
}
fun size(): Int { //插入前判斷,若插入後佔滿則立即擴容,因此size不會大於陣列長度減一
return (tail - head) and (elements.size - 1)
}
fun isEmpty(): Boolean {
return head == tail
}
fun peekFirst(): Int? {
return elements[head]
}
fun peekLast(): Int? {
return elements[(tail -1) and (elements.size - 1)]
}
}