概況
Java的Long類主要的作用就是對基本類型long進行封裝,提供了一些處理long類型的方法,比如long到String類型的轉(zhuǎn)換方法或String類型到long類型的轉(zhuǎn)換方法,當然也包含與其他類型之間的轉(zhuǎn)換方法。除此之外還有一些位相關(guān)的操作。
Java long數(shù)據(jù)類型
long數(shù)據(jù)類型是64位有符號的Java原始數(shù)據(jù)類型。當對整數(shù)的計算結(jié)果可能超出int數(shù)據(jù)類型的范圍時使用。
long數(shù)據(jù)類型范圍是-9,223,372,036,854,775,808至9,223,372,036,854,775,807(-2^63至2^63-1)。
long數(shù)據(jù)類型范圍內(nèi)的所有整數(shù)稱為long類型的整數(shù)字面量。long類型的整數(shù)常數(shù)總是以大寫L或小寫l結(jié)尾。
以下是使用long類型的整數(shù)字面量的示例:
1
2
3
4
5
|
long num1 = 0L; long num2 = 4L; long mum3 = - 3 ; long num4 = 8 ; long num5 = -1L; |
本文主要介紹的是通過JDK源碼分析Long類的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細的介紹吧。
繼承結(jié)構(gòu)
1
2
3
|
--java.lang.Object --java.lang.Number --java.lang.Long |
主要屬性
1
2
3
4
5
|
public static final long MIN_VALUE = 0x8000000000000000L; public static final long MAX_VALUE = 0x7fffffffffffffffL; public static final int BYTES = SIZE / Byte.SIZE; public static final int SIZE = 64 ; public static final Class<Long> TYPE = (Class<Long>) Class.getPrimitiveClass( "long" ); |
- MIN_VALUE靜態(tài)變量表示long能取的最小值,為-2的63次方,被final修飾說明不可變。
- 類似的還有MAX_VALUE,表示long最大值為2的63次方減1。
- SIZE用來表示二進制補碼形式的long值的比特數(shù),值為64,靜態(tài)變量且不可變。
- BYTES用來表示二進制補碼形式的long值的字節(jié)數(shù),值為SIZE除于Byte.SIZE,結(jié)果為8。
-
TYPE的toString的值是long。
Class的getPrimitiveClass是一個native方法,在Class.c中有個Java_java_lang_Class_getPrimitiveClass方法與之對應(yīng),所以JVM層面會通過JVM_FindPrimitiveClass函數(shù)根據(jù)”long”字符串獲得jclass,最終到Java層則為Class<Long>。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
JNIEXPORT jclass JNICALL Java_java_lang_Class_getPrimitiveClass(JNIEnv *env, jclass cls, jstring name) { const char *utfName; jclass result; if (name == NULL) { JNU_ThrowNullPointerException(env, 0 ); return NULL; } utfName = (*env)->GetStringUTFChars(env, name, 0 ); if (utfName == 0 ) return NULL; result = JVM_FindPrimitiveClass(env, utfName); (*env)->ReleaseStringUTFChars(env, name, utfName); return result; } |
當TYPE執(zhí)行toString時,邏輯如下,則其實是getName函數(shù)決定其值,getName通過native方法getName0從JVM層獲取名稱,
1
2
3
4
|
public String toString() { return (isInterface() ? "interface " : (isPrimitive() ? "" : "class " )) + getName(); } |
getName0根據(jù)一個數(shù)組獲得對應(yīng)的名稱,JVM根據(jù)Java層的Class可得到對應(yīng)類型的數(shù)組下標,比如這里下標為11,則名稱為”long”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
const char * type2name_tab[T_CONFLICT+ 1 ] = { NULL, NULL, NULL, NULL, "boolean" , "char" , "float" , "double" , "byte" , "short" , "int" , "long" , "object" , "array" , "void" , "*address*" , "*narrowoop*" , "*conflict*" }; |
LongCache內(nèi)部類
1
2
3
4
5
6
7
8
9
10
|
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(- 128 ) + 127 + 1 ]; static { for ( int i = 0 ; i < cache.length; i++) cache[i] = new Long(i - 128 ); } } |
LongCache是Long的一個內(nèi)部類,它包含了long可能值的Long數(shù)組,默認范圍是[-128,127],它不會像Byte類將所有可能值緩存起來,因為long類型范圍很大,將它們?nèi)烤彺嫫饋泶鷥r太高,而Byte類型就是從-128到127,一共才256個。這里默認只實例化256個Long對象,當Long的值范圍在[-128,127]時則直接從緩存中獲取對應(yīng)的Long對象,不必重新實例化。這些緩存值都是靜態(tài)且final的,避免重復(fù)的實例化和回收。
主要方法
parseLong方法
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
public static long parseLong(String s) throws NumberFormatException { return parseLong(s, 10 ); } public static long parseLong(String s, int radix) throws NumberFormatException { if (s == null ) { throw new NumberFormatException( "null" ); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException( "radix " + radix + " less than Character.MIN_RADIX" ); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException( "radix " + radix + " greater than Character.MAX_RADIX" ); } long result = 0 ; boolean negative = false ; int i = 0 , len = s.length(); long limit = -Long.MAX_VALUE; long multmin; int digit; if (len > 0 ) { char firstChar = s.charAt( 0 ); if (firstChar < '0' ) { // Possible leading "+" or "-" if (firstChar == '-' ) { negative = true ; limit = Long.MIN_VALUE; } else if (firstChar != '+' ) throw NumberFormatException.forInputString(s); if (len == 1 ) // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); i++; } multmin = limit / radix; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); if (digit < 0 ) { throw NumberFormatException.forInputString(s); } if (result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { throw NumberFormatException.forInputString(s); } result -= digit; } } else { throw NumberFormatException.forInputString(s); } return negative ? result : -result; } |
兩個parseLong方法,主要看第二個即可,第一個參數(shù)是待轉(zhuǎn)換的字符串,第二個參數(shù)表示進制數(shù)。怎么更好理解這個參數(shù)呢?舉個例子,Long.parseLong("100",10)
表示十進制的100,所以值為100,而Long.parseLong("100",2)
表示二進制的100,所以值為4。另外如果Long.parseLong("10000000000000000000",10)會拋出java.lang.NumberFormatException
異常。
該方法的邏輯是首先判斷字符串不為空且進制數(shù)在Character.MIN_RADIX和Character.MAX_RADIX之間,即2到36。然后判斷輸入的字符串的長度必須大于0,再根據(jù)第一個字符可能為數(shù)字或負號或正號進行處理。核心處理邏輯是字符串轉(zhuǎn)換數(shù)字,n進制轉(zhuǎn)成十進制辦法基本大家都知道的了,假如357為8進制,則結(jié)果為$3*8^2+5*8^1+7*8^0 = 239$,假如357為十進制,則結(jié)果為$3*10^2+5*10^1+7*10^0 = 357$,上面的轉(zhuǎn)換方法也差不多是根據(jù)此方法,只是稍微轉(zhuǎn)變了思路,方式分別為$((3*8+5)*8+7) = 239$和$((3*10+5)*10+7)=357$。從中可以推出規(guī)則了,從左到右遍歷字符串的每個字符,然后乘以進制數(shù),再加上下一個字符,接著再乘以進制數(shù),再加上下個字符,不斷重復(fù),直到最后一個字符。除此之外另外一個不同就是上面的轉(zhuǎn)換不使用加法來做,全都轉(zhuǎn)成負數(shù)來運算,其實可以看成是等價了,這個很好理解,而為什么要這么做就要歸咎到long類型的范圍了,因為負數(shù)Long.MIN_VALUE
變化為正數(shù)時會導(dǎo)致數(shù)值溢出,所以全部都用負數(shù)來運算。
構(gòu)造函數(shù)
1
2
3
4
5
6
|
public Long(String s) throws NumberFormatException { this .value = parseLong(s, 10 ); } public Long( long value) { this .value = value; } |
包含兩種構(gòu)造函數(shù),分別可以傳入long和String類型。它是通過調(diào)用parseLong方法進行轉(zhuǎn)換的,所以轉(zhuǎn)換邏輯與上面的parseLong方法一樣。
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
40
41
|
static void getChars( long i, int index, char [] buf) { long q; int r; int charPos = index; char sign = 0 ; if (i < 0 ) { sign = '-' ; i = -i; } while (i > Integer.MAX_VALUE) { q = i / 100 ; // really: r = i - (q * 100); r = ( int )(i - ((q << 6 ) + (q << 5 ) + (q << 2 ))); i = q; buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = Integer.DigitTens[r]; } int q2; int i2 = ( int )i; while (i2 >= 65536 ) { q2 = i2 / 100 ; r = i2 - ((q2 << 6 ) + (q2 << 5 ) + (q2 << 2 )); i2 = q2; buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = Integer.DigitTens[r]; } for (;;) { q2 = (i2 * 52429 ) >>> ( 16 + 3 ); r = i2 - ((q2 << 3 ) + (q2 << 1 )); buf[--charPos] = Integer.digits[r]; i2 = q2; if (i2 == 0 ) break ; } if (sign != 0 ) { buf[--charPos] = sign; } } |
該方法主要做的事情是將某個long型數(shù)值放到char數(shù)組里面,比如把357按順序放到char數(shù)組中。這里面處理用了較多技巧,將long拆成高位4個字節(jié)和低位4個字節(jié)處理分開處理,while (i >= Integer.MAX_VALUE)
部分就是處理高位的4個字節(jié),每次處理2位數(shù),這里有個特殊的地方((q << 6) + (q << 5) + (q << 2))其實等于q*100,Integer.DigitTens
和Integer.DigitOnes
數(shù)組在前面Integer文章中已經(jīng)講過它的作用了,用來獲取十位和個位。
接著看怎么處理低4個字節(jié),它繼續(xù)將4個字節(jié)分為高位2個字節(jié)和低位2個字節(jié),while (i >= 65536)
部分就是處理高位的兩個字節(jié),每次處理2位數(shù),處理邏輯與高位4個字節(jié)的處理邏輯一樣。
再看接下去的低位的兩個字節(jié)怎么處理,其實本質(zhì)也是求余思想,但又用了一些技巧,比如(i * 52429) >>> (16+3)
其實約等于i/10
, ((q << 3) + (q << 1))
其實等于q*10,然后再通過Integer.digits
數(shù)組獲取到對應(yīng)的字符??梢钥吹降臀惶幚頃r它盡量避開了除法,取而代之的是用乘法和右移來實現(xiàn),可見除法是一個比較耗時的操作,比起乘法和移位。另外也可以看到能用移位和加法來實現(xiàn)乘法的地方也盡量不用乘法,這也說明乘法比起它們更加耗時。而高位處理時沒有用移位是因為做乘法后可能會溢出。
toString方法
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
|
public static String toString( long i) { if (i == Long.MIN_VALUE) return "-9223372036854775808" ; int size = (i < 0 ) ? stringSize(-i) + 1 : stringSize(i); char [] buf = new char [size]; getChars(i, size, buf); return new String(buf, true ); } public String toString() { return toString(value); } public static String toString( long i, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10 ; if (radix == 10 ) return toString(i); char [] buf = new char [ 65 ]; int charPos = 64 ; boolean negative = (i < 0 ); if (!negative) { i = -i; } while (i <= -radix) { buf[charPos--] = Integer.digits[( int )(-(i % radix))]; i = i / radix; } buf[charPos] = Integer.digits[( int )(-i)]; if (negative) { buf[--charPos] = '-' ; } return new String(buf, charPos, ( 65 - charPos)); } |
一共有3個toString方法,兩個靜態(tài)方法一個是非靜態(tài)方法,第一個toString方法很簡單,就是先用stringSize得到數(shù)字是多少位,再用getChars獲取數(shù)字對應(yīng)的char數(shù)組,最后返回一個String類型。第二個toString調(diào)用第一個toString,沒啥好說。第三個toString方法是帶了進制信息的,它會轉(zhuǎn)換成對應(yīng)進制的字符串。凡是不在2到36進制范圍之間的都會被處理成10進制,我們都知道從十進制轉(zhuǎn)成其他進制時就是不斷地除于進制數(shù)得到余數(shù),然后把余數(shù)反過來串起來就是最后結(jié)果,所以這里其實也是這樣子做的,得到余數(shù)后通過digits數(shù)組獲取到對應(yīng)的字符,而且這里是用負數(shù)的形式來運算的。
valueOf方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public static Long valueOf( long l) { final int offset = 128 ; if (l >= - 128 && l <= 127 ) { // will cache return LongCache.cache[( int )l + offset]; } return new Long(l); } public static Long valueOf(String s) throws NumberFormatException { return Long.valueOf(parseLong(s, 10 )); } public static Long valueOf(String s, int radix) throws NumberFormatException { return Long.valueOf(parseLong(s, radix)); } |
有三個valueOf方法,核心邏輯在第一個valueOf方法中,因為LongCache緩存了[-128,127]值的Long對象,對于在范圍內(nèi)的直接從LongCache的數(shù)組中獲取對應(yīng)的Long對象即可,而在范圍外的則需要重新實例化了。
decode方法
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
40
|
public static Long decode(String nm) throws NumberFormatException { int radix = 10 ; int index = 0 ; boolean negative = false ; Long result; if (nm.length() == 0 ) throw new NumberFormatException( "Zero length string" ); char firstChar = nm.charAt( 0 ); if (firstChar == '-' ) { negative = true ; index++; } else if (firstChar == '+' ) index++; if (nm.startsWith( "0x" , index) || nm.startsWith( "0X" , index)) { index += 2 ; radix = 16 ; } else if (nm.startsWith( "#" , index)) { index ++; radix = 16 ; } else if (nm.startsWith( "0" , index) && nm.length() > 1 + index) { index ++; radix = 8 ; } if (nm.startsWith( "-" , index) || nm.startsWith( "+" , index)) throw new NumberFormatException( "Sign character in wrong position" ); try { result = Long.valueOf(nm.substring(index), radix); result = negative ? Long.valueOf(-result.longValue()) : result; } catch (NumberFormatException e) { String constant = negative ? ( "-" + nm.substring(index)) : nm.substring(index); result = Long.valueOf(constant, radix); } return result; } |
decode方法主要作用是解碼字符串轉(zhuǎn)成Long型,比如Long.decode("11")
的結(jié)果為11;Long.decode("0x11")
和Long.decode("#11")
結(jié)果都為17,因為0x和#開頭的會被處理成十六進制;Long.decode("011")
結(jié)果為9,因為0開頭會被處理成8進制。
xxxValue方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public byte byteValue() { return ( byte )value; } public short shortValue() { return ( short )value; } public int intValue() { return ( int )value; } public long longValue() { return value; } public float floatValue() { return ( float )value; } public double doubleValue() { return ( double )value; } |
包括shortValue、intValue、longValue、byteValue、floatValue和doubleValue等方法,其實就是轉(zhuǎn)換成對應(yīng)的類型。
hashCode方法
1
2
3
4
5
6
|
public int hashCode() { return Long.hashCode(value); } public static int hashCode( long value) { return ( int )(value ^ (value >>> 32 )); } |
可以看到hashCode方法返回的事int類型,首先將long型值無符號右移32位,再和原來的值進行異或運算,最后返回int類型值。
hashCode方法
1
2
3
4
5
6
|
public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false ; } |
比較是否相同時先判斷是不是Long類型再比較值。
compare方法
1
2
3
|
public static int compare( long x, long y) { return (x < y) ? - 1 : ((x == y) ? 0 : 1 ); } |
x小于y則返回-1,相等則返回0,否則返回1。
無符號轉(zhuǎn)換
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
40
41
42
43
|
private static BigInteger toUnsignedBigInteger( long i) { if (i >= 0L) return BigInteger.valueOf(i); else { int upper = ( int ) (i >>> 32 ); int lower = ( int ) i; return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft( 32 ). add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); } } public static String toUnsignedString( long i) { return toUnsignedString(i, 10 ); } public static String toUnsignedString( long i, int radix) { if (i >= 0 ) return toString(i, radix); else { switch (radix) { case 2 : return toBinaryString(i); case 4 : return toUnsignedString0(i, 2 ); case 8 : return toOctalString(i); case 10 : long quot = (i >>> 1 ) / 5 ; long rem = i - quot * 10 ; return toString(quot) + rem; case 16 : return toHexString(i); case 32 : return toUnsignedString0(i, 5 ); default : return toUnsignedBigInteger(i).toString(radix); } } } |
toUnsignedBigInteger方法將long轉(zhuǎn)成BigInteger類型,主要用BigInteger.valueOf進行轉(zhuǎn)換,如果小于0則需要先轉(zhuǎn)成高4字節(jié)和低4字節(jié),然后再轉(zhuǎn)換。
toUnsignedString方法中,對于大于0的long值直接用toString轉(zhuǎn)換,而小于0的則要按照進制不同分別做不同處理。
bitCount方法
1
2
3
4
5
6
7
8
9
10
|
public static int bitCount( long i) { // HD, Figure 5-14 i = i - ((i >>> 1 ) & 0x5555555555555555L); i = (i & 0x3333333333333333L) + ((i >>> 2 ) & 0x3333333333333333L); i = (i + (i >>> 4 )) & 0x0f0f0f0f0f0f0f0fL; i = i + (i >>> 8 ); i = i + (i >>> 16 ); i = i + (i >>> 32 ); return ( int )i & 0x7f ; } |
該方法主要用于計算二進制數(shù)中1的個數(shù)。一看有點懵,都是移位和加減操作。先將重要的列出來,0x5555555555555555L等于0101010101010101010101010101010101010101010101010101010101010101,0x3333333333333333L等于0011001100110011001100110011001100110011001100110011001100110011,0x0f0f0f0f0f0f0f0fL等于0000111100001111000011110000111100001111000011110000111100001111。它的核心思想就是先每兩位一組統(tǒng)計看有多少個1,比如10011111則每兩位有1、1、2、2個1,記為01011010,然后再算每四位一組看有多少個1,而01011010則每四位有2、4個1,記為00100100,接著每8位一組就為00000110,接著16位,32位,64位,最終在與0x7f進行與運算,得到的數(shù)即為1的個數(shù)。
highestOneBit方法
1
2
3
4
5
6
7
8
9
10
|
public static long highestOneBit( long i) { // HD, Figure 3-1 i |= (i >> 1 ); i |= (i >> 2 ); i |= (i >> 4 ); i |= (i >> 8 ); i |= (i >> 16 ); i |= (i >> 32 ); return i - (i >>> 1 ); } |
該方法返回i的二進制中最高位的1,其他全為0的值。比如i=10時,二進制即為1010,最高位的1,其他為0,則是1000。如果i=0,則返回0。如果i為負數(shù)則固定返回-2147483648,因為負數(shù)的最高位一定是1,即有1000,0000,0000,0000,0000,0000,0000,0000。這一堆移位操作是什么意思?其實也不難理解,將i右移一位再或操作,則最高位1的右邊也為1了,接著再右移兩位并或操作,則右邊1+2=3位都為1了,接著1+2+4=7位都為1,直到1+2+4+8+16+32=63都為1,最后用i - (i >>> 1)自然得到最終結(jié)果。
lowestOneBit方法
1
2
3
|
public static long lowestOneBit( long i) { return i & -i; } |
與highestOneBit方法對應(yīng),lowestOneBit獲取最低位1,其他全為0的值。這個操作較簡單,先取負數(shù),這個過程需要對正數(shù)的i取反碼然后再加1,得到的結(jié)果和i進行與操作,剛好就是最低位1其他為0的值了。
numberOfLeadingZeros方法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public static int numberOfLeadingZeros( long i) { if (i == 0 ) return 64 ; int n = 1 ; int x = ( int )(i >>> 32 ); if (x == 0 ) { n += 32 ; x = ( int )i; } if (x >>> 16 == 0 ) { n += 16 ; x <<= 16 ; } if (x >>> 24 == 0 ) { n += 8 ; x <<= 8 ; } if (x >>> 28 == 0 ) { n += 4 ; x <<= 4 ; } if (x >>> 30 == 0 ) { n += 2 ; x <<= 2 ; } n -= x >>> 31 ; return n; } |
該方法返回i的二進制從頭開始有多少個0。i為0的話則有64個0。這里處理其實是體現(xiàn)了二分查找思想的,先看高32位是否為0,是的話則至少有32個0,否則左移16位繼續(xù)往下判斷,接著右移24位看是不是為0,是的話則至少有16+8=24個0,以此類推,直到最后得到結(jié)果。
numberOfTrailingZeros方法
1
2
3
4
5
6
7
8
9
10
11
|
public static int numberOfTrailingZeros( long i) { int x, y; if (i == 0 ) return 64 ; int n = 63 ; y = ( int )i; if (y != 0 ) { n = n - 32 ; x = y; } else x = ( int )(i>>> 32 ); y = x << 16 ; if (y != 0 ) { n = n - 16 ; x = y; } y = x << 8 ; if (y != 0 ) { n = n - 8 ; x = y; } y = x << 4 ; if (y != 0 ) { n = n - 4 ; x = y; } y = x << 2 ; if (y != 0 ) { n = n - 2 ; x = y; } return n - ((x << 1 ) >>> 31 ); } |
與前面的numberOfLeadingZeros方法對應(yīng),該方法返回i的二進制從尾開始有多少個0。它的思想和前面的類似,也是基于二分查找思想,詳細步驟不再贅述。
reverse方法
1
2
3
4
5
6
7
8
9
|
public static long reverse( long i) { i = (i & 0x5555555555555555L) << 1 | (i >>> 1 ) & 0x5555555555555555L; i = (i & 0x3333333333333333L) << 2 | (i >>> 2 ) & 0x3333333333333333L; i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4 ) & 0x0f0f0f0f0f0f0f0fL; i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8 ) & 0x00ff00ff00ff00ffL; i = (i << 48 ) | ((i & 0xffff0000L) << 16 ) | ((i >>> 16 ) & 0xffff0000L) | (i >>> 48 ); return i; } |
該方法即是將i進行反轉(zhuǎn),反轉(zhuǎn)就是第1位與第64位對調(diào),第二位與第63位對調(diào),以此類推。它的核心思想是先將相鄰兩位進行對換,比如10100111對換01011011,接著再將相鄰四位進行對換,對換后為10101101,接著將相鄰八位進行對換,最后把64位中中間的32位對換,然后最高16位再和最低16位對換。
toHexString和toOctalString方法
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
|
public static String toHexString( long i) { return toUnsignedString0(i, 4 ); } public static String toOctalString( long i) { return toUnsignedString0(i, 3 ); } public static String toBinaryString( long i) { return toUnsignedString0(i, 1 ); } static String toUnsignedString0( long val, int shift) { int mag = Long.SIZE - Long.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1 )) / shift), 1 ); char [] buf = new char [chars]; formatUnsignedLong(val, shift, buf, 0 , chars); return new String(buf, true ); } static int formatUnsignedLong( long val, int shift, char [] buf, int offset, int len) { int charPos = len; int radix = 1 << shift; int mask = radix - 1 ; do { buf[offset + --charPos] = Integer.digits[(( int ) val) & mask]; val >>>= shift; } while (val != 0 && charPos > 0 ); return charPos; } |
這幾個方法類似,合到一起講??疵志椭擂D(zhuǎn)成2進制、8進制和16進制的字符串??梢钥吹蕉际情g接調(diào)用toUnsignedString0方法,該方法會先計算轉(zhuǎn)換成對應(yīng)進制需要的字符數(shù),然后再通過formatUnsignedInt方法來填充字符數(shù)組,該方法做的事情就是使用進制之間的轉(zhuǎn)換方法來獲取對應(yīng)的字符。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。
原文鏈接:http://blog.csdn.net/wangyangzhizhou/article/details/78026810