激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

香港云服务器
服務(wù)器之家 - 編程語言 - Java教程 - 基于jdk1.8的Java源碼詳解 Integer

基于jdk1.8的Java源碼詳解 Integer

2019-07-07 17:17rainple Java教程

這篇文章主要介紹了基于jdk1.8的Java源碼詳解 Integer,Integer是int的Warpper類,是面向?qū)ο蟮募碠OP的對象類型,,需要的朋友可以參考下

1public final class Integer extends Number implements Comparable<Integer>

Integer 由final修飾了,所以該類不能夠被繼承,同時 Integer 繼承了Number類,因此可以將Integer轉(zhuǎn)換成 int 、double、float、long、byte和short類型的數(shù)據(jù),另外,也實現(xiàn)了comparable接口,因此Integer類也可以進行自然排序。

構(gòu)造方法只有兩個:

1public Integer(int value) {
2this.value = value;
3}
1public Integer(String s) throws NumberFormatException {
2this.value = parseInt(s, 10);
3}

我們主要看第二個構(gòu)造方法,傳入一個字符串,然后調(diào)用parseInt方法,接下來進入parseInt的源碼:

01public static int parseInt(String s, int radix)
02throws NumberFormatException
03{
04/*
05* WARNING: This method may be invoked early during VM initialization
06* before IntegerCache is initialized. Care must be taken to not use
07* the valueOf method.
08*/
09if (s == null) {
10throw new NumberFormatException("null");
11}
12if (radix < Character.MIN_RADIX) {
13throw new NumberFormatException("radix " + radix +
14" less than Character.MIN_RADIX");
15}
16if (radix > Character.MAX_RADIX) {
17throw new NumberFormatException("radix " + radix +
18" greater than Character.MAX_RADIX");
19}
20int result = 0;
21// //是否為負(fù)數(shù)
22boolean negative = false;
23int i = 0, len = s.length();
24//這里加個負(fù)號是防止數(shù)據(jù)溢出,int的數(shù)值范圍 -2的31次方到2的31次方減一
25int limit = -Integer.MAX_VALUE;
26//最小基數(shù)
27int multmin;
28//十進制數(shù)字
29int digit;
30if (len > 0) {
31char firstChar = s.charAt(0);
32//第一個字符小于0,有可能是"-","+"或其他字符
33if (firstChar < '0') { // Possible leading "+" or "-"
34//為負(fù)數(shù)
35if (firstChar == '-') {
36negative = true;
37limit = Integer.MIN_VALUE;
38} else if (firstChar != '+')//非數(shù)字
39throw NumberFormatException.forInputString(s);
40if (len == 1) // Cannot have lone "+" or "-"
41throw NumberFormatException.forInputString(s);
42i++;
43}
44/**
45* 最小基數(shù),主要防止 result *= radix; 這個操作時數(shù)據(jù)過大
46* 導(dǎo)致數(shù)據(jù)丟失的問題,因為所以帶符號32位int類型整數(shù)為-2147483648~2147483647
47*/
48multmin = limit / radix;
49while (i < len) {
50// Accumulating negatively avoids surprises near MAX_VALUE
51//轉(zhuǎn)換十進制,這里獲取的是radix進制下相對應(yīng)的10進制數(shù)字,如:
52//Character.digit('a',16),則返回 10;
53//若輸入字符不在進制的范圍之內(nèi),則返回 -1:
54//Character.digit('t',16),返回 -1,Character.digit('a',10),返回 -1
55digit = Character.digit(s.charAt(i++),radix);
56//返回-1說明字符非法
57if (digit < 0) {
58throw NumberFormatException.forInputString(s);
59}
60//超過了數(shù)據(jù)范圍
61if (result < multmin) {
62throw NumberFormatException.forInputString(s);
63}
64/**
65*在轉(zhuǎn)換時從高位向地位方向轉(zhuǎn)換
66*/
67result *= radix;
68if (result < limit + digit) {
69throw NumberFormatException.forInputString(s);
70}
71result -= digit;
72}
73} else {
74throw NumberFormatException.forInputString(s);
75}
76return negative ? result : -result;
77}

這個方法中最核心的步驟是1、result *= radix; 2、result -= digit; 經(jīng)過這兩個步驟將字符串轉(zhuǎn)換成數(shù)值類型。大概流程是這樣的:

  1. 假如字符串"1234" 轉(zhuǎn)換成int類型,result 的初始值為0,radix默認(rèn)為10;
  2. 首先截取字符串的第一個字符1(這里忽略各種檢查),經(jīng)過第一步計算 result = 0*10 = 0;第二部計算 result = 0 - 1 = -1;
  3. 第一遍循環(huán)結(jié)束后,result 的值 變成了 -1
  4. 截取第二個字符 2 ,result = -1 * 10 = -10,result = -10 - 2 = -12;
  5. 截取第三個字符 3 ,result = -12 * 10 = -120,result = -120 - 3 = -123;
  6. 截取第四個字符 4 ,result = -123 * 10 = -1230 ,result = -1230-4 = -1234;
  7. 循環(huán)結(jié)束,此時result的值為 -1234,完成字符串向整數(shù)型的轉(zhuǎn)換,返回是取反即可。

面我將從一個面試題引出問題,然后通過閱讀源碼來解決這個問題。

01public static void main(String[] args) {
02Integer i1 = 100;
03Integer i2 = 100;
04Integer i3 = 200;
05Integer i4 = 200;
06Integer i5 = Integer.valueOf(100);
07Integer i6 = Integer.valueOf(100);
08Integer i7 = new Integer(100);
09System.out.println("i1 == i2 的結(jié)果是:" + (i1 == i2));
10System.out.println("i3 == i4 的結(jié)果是:" + (i3 == i4));
11System.out.println("i5 == i6 的結(jié)果是:" + (i5 == i6));
12System.out.println("i1 == i5 的結(jié)果是:" + (i1 == i5));
13System.out.println("i1 == i7 的結(jié)果是:" + (i1 == i7));
14}

運行結(jié)果為:

1i1 == i2 的結(jié)果是:true
2i3 == i4 的結(jié)果是:false
3i5 == i6 的結(jié)果是:true
4i1 == i5 的結(jié)果是:true
5i1 == i7 的結(jié)果是:false

我們先來看第一和第二條結(jié)果,同樣是比較兩個相同數(shù)值,為什么會有不同的結(jié)果呢?接下我將通過源碼來解釋原因。

首先,我們通過編譯獲取到class文件的字節(jié)碼

基于jdk1.8的Java源碼詳解 Integer

從圖中我們可以看到,在執(zhí)行 Integer i1 = 100 這條命令的時候,編譯器會調(diào)用Integer中的靜態(tài)方法 valueOf,接下來我們看看 valueOf方法是怎么實現(xiàn)的吧。

1public static Integer valueOf(int i) {
2if (i >= IntegerCache.low && i <= IntegerCache.high)
3return IntegerCache.cache[i + (-IntegerCache.low)];
4return new Integer(i);
5}

這個代碼看起來很簡單,Integer 中有一個靜態(tài)內(nèi)部類 IntegerCache,調(diào)用該方法時首先會判斷該值是否在緩存的范圍內(nèi),如果在則直接將緩存中的數(shù)值返回,否則返回一個新對象。看到這里我們似乎已經(jīng)知道了上面的問題的答案了,接下來繼續(xù)看靜態(tài)內(nèi)部類吧

01private static class IntegerCache {
02static final int low = -128;
03static final int high;
04static final Integer cache[];
05static {
06// high value may be configured by property
07//緩存范圍最小(也是默認(rèn)范圍)為 (-128)~ 127,如果配置java.lang.Integer.IntegerCache.high
08//high 的值可從配置文件中讀取
09int h = 127;
10String integerCacheHighPropValue =
11sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
12if (integerCacheHighPropValue != null) {
13try {
14int i = parseInt(integerCacheHighPropValue);
15//獲取配置文件和127之間的最大值
16i = Math.max(i, 127);
17// Maximum array size is Integer.MAX_VALUE
18//最大值范圍
19h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
20} catch( NumberFormatException nfe) {
21// If the property cannot be parsed into an int, ignore it.
22}
23}
24high = h;
25//創(chuàng)建緩存數(shù)組
26cache = new Integer[(high - low) + 1];
27int j = low;
28//將數(shù)字緩存起來默認(rèn) -128 ~ 127
29for(int k = 0; k < cache.length; k++)
30cache[k] = new Integer(j++);
31// range [-128, 127] must be interned (JLS7 5.1.7)
32assert IntegerCache.high >= 127;
33}
34private IntegerCache() {}
35}

我們知道內(nèi)部類只有在所在類實例化時才會被實例化,而且只會實例化一次,緩存操作是在靜態(tài)代碼塊中完成,也就是說在類被實例化的時候數(shù)據(jù)就已經(jīng)被緩存好了,接下使用的時候可以直接使用緩存的數(shù)據(jù)。

現(xiàn)在我們回歸到上面的問題,結(jié)果1中兩個數(shù)據(jù)均為 100,在緩存的范圍中,因此i1和i2都指向的是同一個內(nèi)存地址,因此返回true。結(jié)果2中 兩個數(shù)都是200,超出了緩存的范圍,所以直接new 出了兩個對象,因此他們的內(nèi)存地址不一致,返回結(jié)果為false;另外,使用valueOf 和 使用 = 操作符賦值時一樣的,所以結(jié)果3和結(jié)果4返回結(jié)果為 true,結(jié)果5中 是直接使用new關(guān)鍵字創(chuàng)建對象,所以他們的內(nèi)存地址肯定不一致,結(jié)果為false。

那么,現(xiàn)在問題又來了,那我怎么判斷兩個整數(shù)的大小呢?繼續(xù)看源碼

01/**
02* The value of the {@code Integer}.
03*
04* @serial
05*/
06private final int value;
07public boolean equals(Object obj) {
08if (obj instanceof Integer) {
09return value == ((Integer)obj).intValue();
10}
11return false;
12}
13public int intValue() {
14return value;
15}

是的,沒錯,比較兩個數(shù)值大小時可以使用equals方法來比較,源碼中value的類型為 int型,intValue返回的也是value,因此可以判斷兩個數(shù)的大小。

1public static void main(String[] args) {
2Integer i1 = 200;
3Integer i2 = 200;
4System.out.println("i1 == i2 的結(jié)果是:" + i1.equals(i2)); //true
5}

補充:equals 與 == 的區(qū)別:

equals 比較的是兩個數(shù)值的大小,== 有兩種情況,如果比較的是 基本數(shù)據(jù)類型,則 == 跟equals一樣都是比較的大小,如果是引用類型或數(shù)組,則比較是內(nèi)存地址。

getChars方法:

01static void getChars(int i, int index, char[] buf) {
02int q, r;
03int charPos = index;
04char sign = 0;
05 
06if (i < 0) {
07sign = '-';
08i = -i;
09}
10 
11// Generate two digits per iteration
12//每次循環(huán)獲取后兩位數(shù)
13while (i >= 65536) {
14q = i / 100;
15// really: r = i - (q * 100);
16//使用位移運算的效率高于乘法運算,r為后兩位數(shù)
17r = i - ((q << 6) + (q << 5) + (q << 2));
18i = q;
19//獲取后兩位數(shù)的個位
20buf [--charPos] = DigitOnes[r];
21//十位
22buf [--charPos] = DigitTens[r];
23}
24 
25// Fall thru to fast mode for smaller numbers
26// assert(i <= 65536, i);
27//每次只取個位數(shù)
28for (;;) {
29//相當(dāng)于i*(52429/524288)=i*0.10000038146972656=i*0.1=i/10
30//這里選 52429 和 2的19次方相除,得到的結(jié)果精度更加高,更加接近于 i/10的結(jié)果
31//之所以要這樣轉(zhuǎn)換,是因為在計算機運算中位移的效率 > 乘法效率 > 除法效率
32q = (i * 52429) >>> (16+3);
33r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
34buf [--charPos] = digits [r];
35i = q;
36if (i == 0) break;
37}
38if (sign != 0) {
39buf [--charPos] = sign;
40}
41}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
  • Java教程SpringBoot引入Thymeleaf的實現(xiàn)方法

    SpringBoot引入Thymeleaf的實現(xiàn)方法

    這篇文章主要介紹了SpringBoot引入Thymeleaf的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下...

    Bobby6472021-07-28
  • Java教程JAVA中通過自定義注解進行數(shù)據(jù)驗證的方法

    JAVA中通過自定義注解進行數(shù)據(jù)驗證的方法

    java 自定義注解驗證可自己添加所需要的注解,下面這篇文章主要給大家介紹了關(guān)于JAVA中通過自定義注解進行數(shù)據(jù)驗證的相關(guān)資料,文中通過示例代碼介紹...

    Decouple6362021-05-25
  • Java教程java 中鎖的性能提高辦法

    java 中鎖的性能提高辦法

    這篇文章主要介紹了java 中鎖的性能提高辦法的相關(guān)資料,需要的朋友可以參考下...

    Java之家3092020-08-13
  • Java教程Java list.remove( )方法注意事項

    Java list.remove( )方法注意事項

    這篇文章主要介紹了Java list.remove( )方法注意事項,非常簡單易懂,需要的朋友可以參考下...

    妖久9552021-05-25
  • Java教程springboot ehcache 配置使用方法代碼詳解

    springboot ehcache 配置使用方法代碼詳解

    EhCache是一個比較成熟的Java緩存框架,Springboot對ehcache的使用非常支持,所以在Springboot中只需做些配置就可使用,且使用方式也簡易,今天給大家分享spri...

    m1719309529412912021-09-16
  • Java教程Java之Springcloud Feign組件詳解

    Java之Springcloud Feign組件詳解

    這篇文章主要介紹了Java之Springcloud Feign組件詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下...

    深情以改10322021-11-12
  • Java教程淺談Java(SpringBoot)基于zookeeper的分布式鎖實現(xiàn)

    淺談Java(SpringBoot)基于zookeeper的分布式鎖實現(xiàn)

    這篇文章主要介紹了Java(SpringBoot)基于zookeeper的分布式鎖實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的...

    LJY_SUPER5742021-07-21
  • Java教程JavaWeb 實現(xiàn)驗證碼功能(demo)

    JavaWeb 實現(xiàn)驗證碼功能(demo)

    在 WEB-APP 中一般應(yīng)用于:登錄、注冊、買某票、秒殺等場景,大家都接觸過這個驗證碼操作,今天小編通過實例代碼給大家講解javaweb實現(xiàn)驗證碼功能,需要...

    java教程網(wǎng)12832020-08-05
637
主站蜘蛛池模板: 日日狠狠久久 | 99精品视频一区二区三区 | 毛片在线视频观看 | 黄色免费av网站 | 蜜桃传媒视频麻豆第一区免费观看 | 午夜视频中文字幕 | 免看黄大片aa | 91九色视频在线观看 | 免费日本一区二区 | av黄色在线免费观看 | 色淫影院| 黄在线免费 | 久久久日韩精品一区二区三区 | 狠狠操视频网站 | 成码无人av片在线观看网站 | 香蕉视频1024 | 日本在线免费观看视频 | 亚洲一区播放 | 吾色视频 | 免费一级肉体全黄毛片 | 黄色免费在线视频网站 | 久久精品视频7 | 国产日韩三区 | 成人精品免费在线观看 | v片在线看 | 成人在线视频播放 | 精品国产乱码一区二区 | 国产精品午夜未成人免费观看 | 久久成人国产精品入口 | 黄色免费不卡视频 | 免费国产一区二区视频 | 草碰人人| 密室逃脱第一季免费观看完整在线 | av手机在线免费播放 | 欧美一级黄色网 | 欧美成人一区免费视频 | 九九热精品在线视频 | 日本在线视频一区二区三区 | 91精品国产综合久久男男 | 成人福利视频在线 | 日韩电影一区二区 |