国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 通過JDK源碼角度分析Long類詳解

通過JDK源碼角度分析Long類詳解

2021-02-01 11:56汪洋之舟---seaboat Java教程

這篇文章主要給大家介紹了關于通過JDK源碼角度分析Long類的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用long類具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

概況

Java的Long類主要的作用就是對基本類型long進行封裝,提供了一些處理long類型的方法,比如long到String類型的轉(zhuǎn)換方法或String類型到long類型的轉(zhuǎn)換方法,當然也包含與其他類型之間的轉(zhuǎn)換方法。除此之外還有一些位相關的操作。

Java long數(shù)據(jù)類型

long數(shù)據(jù)類型是64位有符號的Java原始數(shù)據(jù)類型。當對整數(shù)的計算結果可能超出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結尾。

以下是使用long類型的整數(shù)字面量的示例:

?
1
2
3
4
5
long num1 = 0L;
long num2 = 4L;
long mum3 = -3;
long num4 = 8;
long num5 = -1L;

本文主要介紹的是通過JDK源碼分析Long類的相關內(nèi)容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

繼承結構

?
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,結果為8。
  • TYPE的toString的值是long。
    Class的getPrimitiveClass是一個native方法,在Class.c中有個Java_java_lang_Class_getPrimitiveClass方法與之對應,所以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ù)組獲得對應的名稱,JVM根據(jù)Java層的Class可得到對應類型的數(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]時則直接從緩存中獲取對應的Long對象,不必重新實例化。這些緩存值都是靜態(tài)且final的,避免重復的實例化和回收。

主要方法

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進制,則結果為$3*8^2+5*8^1+7*8^0 = 239$,假如357為十進制,則結果為$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ù),再加上下個字符,不斷重復,直到最后一個字符。除此之外另外一個不同就是上面的轉(zhuǎn)換不使用加法來做,全都轉(zhuǎn)成負數(shù)來運算,其實可以看成是等價了,這個很好理解,而為什么要這么做就要歸咎到long類型的范圍了,因為負數(shù)Long.MIN_VALUE變化為正數(shù)時會導致數(shù)值溢出,所以全部都用負數(shù)來運算。

構造函數(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;
 }

包含兩種構造函數(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.DigitTensInteger.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ù)組獲取到對應的字符。可以看到低位處理時它盡量避開了除法,取而代之的是用乘法和右移來實現(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ù)字對應的char數(shù)組,最后返回一個String類型。第二個toString調(diào)用第一個toString,沒啥好說。第三個toString方法是帶了進制信息的,它會轉(zhuǎn)換成對應進制的字符串。凡是不在2到36進制范圍之間的都會被處理成10進制,我們都知道從十進制轉(zhuǎn)成其他進制時就是不斷地除于進制數(shù)得到余數(shù),然后把余數(shù)反過來串起來就是最后結果,所以這里其實也是這樣子做的,得到余數(shù)后通過digits數(shù)組獲取到對應的字符,而且這里是用負數(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ù)組中獲取對應的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")的結果為11;Long.decode("0x11")Long.decode("#11")結果都為17,因為0x和#開頭的會被處理成十六進制;Long.decode("011")結果為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)換成對應的類型。

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)自然得到最終結果。

lowestOneBit方法

?
1
2
3
public static long lowestOneBit(long i) {
  return i & -i;
 }

與highestOneBit方法對應,lowestOneBit獲取最低位1,其他全為0的值。這個操作較簡單,先取負數(shù),這個過程需要對正數(shù)的i取反碼然后再加1,得到的結果和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,以此類推,直到最后得到結果。

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方法對應,該方法返回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;
 }

這幾個方法類似,合到一起講。看名字就知道轉(zhuǎn)成2進制、8進制和16進制的字符串。可以看到都是間接調(diào)用toUnsignedString0方法,該方法會先計算轉(zhuǎn)換成對應進制需要的字符數(shù),然后再通過formatUnsignedInt方法來填充字符數(shù)組,該方法做的事情就是使用進制之間的轉(zhuǎn)換方法來獲取對應的字符。

總結

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:http://blog.csdn.net/wangyangzhizhou/article/details/78026810

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 亚洲免费一区 | 视频1区2区 | 伊人精品影院 | 国产成人99久久亚洲综合精品 | 综合久久综合久久 | 成人免费网站 | 另类亚洲专区 | 探花av在线 | 日本三级视频在线观看 | 天堂资源| 日本黄色一级电影 | 久久久精品一区二区 | 黄色毛片在线视频 | 亚洲精品一区二区 | 亚洲特黄av| 国产精品久久影院 | 亚洲不卡在线 | 国产亚洲人成网站在线观看 | 日韩免费电影 | 欧美亚洲视频在线观看 | 亚洲国产精品一二三区 | 久久久综合视频 | 毛片网站大全 | 日本在线免费 | 一级在线 | www.久久精品 | 久久爱综合| 欧美一区不卡 | 中文字幕在线精品 | 精品国产一级 | 福利社午夜影院 | 成人网av | av电影免费在线 | 欧洲亚洲精品久久久久 | 久草福利在线视频 | 国产伦精品一区二区三区高清 | 欧美日韩一区二区三区在线观看 | 久久久国产一区二区三区 | 中国a毛片 | 狠狠淫| 一区免费看 |