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

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

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - 詳解Java 自動裝箱與拆箱的實現原理

詳解Java 自動裝箱與拆箱的實現原理

2020-09-16 15:23jijs JAVA教程

本篇文章主要介紹了詳解Java 自動裝箱與拆箱的實現原理,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

什么是自動裝箱拆箱

自動裝箱就是Java自動將原始類型值轉換成對應的對象,比如將int的變量轉換成Integer對象,這個過程叫做裝箱,反之將Integer對象轉換成int類型值,這個過程叫做拆箱。因為這里的裝箱和拆箱是自動進行的非人為轉換,所以就稱作為自動裝箱和拆箱。原始類型byte, short, char, int, long, float, double 和 boolean 對應的封裝類為Byte, Short, Character, Integer, Long, Float, Double, Boolean。

下面例子是自動裝箱和拆箱帶來的疑惑

 

?
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 Test {
  public static void main(String[] args) {  
    test();
  }
 
  public static void test() {
    int i = 40;
    int i0 = 40;
    Integer i1 = 40;
    Integer i2 = 40;
    Integer i3 = 0;
    Integer i4 = new Integer(40);
    Integer i5 = new Integer(40);
    Integer i6 = new Integer(0);
    Double d1=1.0;
    Double d2=1.0;
 
    System.out.println("i=i0\t" + (i == i0));
    System.out.println("i1=i2\t" + (i1 == i2));
    System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));
    System.out.println("i4=i5\t" + (i4 == i5));
    System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));  
    System.out.println("d1=d2\t" + (d1==d2)); 
 
    System.out.println();    
  }
}

請看下面的輸出結果跟你預期的一樣嗎?

輸出的結果:

i=i0    true
i1=i2   true
i1=i2+i3    true
i4=i5   false
i4=i5+i6    true
d1=d2 false

為什么會這樣?帶著疑問繼續往下看。

自動裝箱和拆箱的原理

自動裝箱時編譯器調用valueOf將原始類型值轉換成對象,同時自動拆箱時,編譯器通過調用類似intValue(),doubleValue()這類的方法將對象轉換成原始類型值。

明白自動裝箱和拆箱的原理后,我們帶著上面的疑問進行分析下Integer的自動裝箱的實現源碼。如下:

?
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
public static Integer valueOf(int i) {
  //判斷i是否在-128和127之間,如果不在此范圍,則從IntegerCache中獲取包裝類的實例。否則new一個新實例
  if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
  return new Integer(i);
}
 
 
//使用亨元模式,來減少對象的創建(亨元設計模式大家有必要了解一下,我認為是最簡單的設計模式,也許大家經常在項目中使用,不知道他的名字而已)
private static class IntegerCache {
  static final int low = -128;
  static final int high;
  static final Integer cache[];
 
  //靜態方法,類加載的時候進行初始化cache[],靜態變量存放在常量池中
  static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
      sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
      try {
        int i = parseInt(integerCacheHighPropValue);
        i = Math.max(i, 127);
        // Maximum array size is Integer.MAX_VALUE
        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
      } catch( NumberFormatException nfe) {
        // If the property cannot be parsed into an int, ignore it.
      }
    }
    high = h;
 
    cache = new Integer[(high - low) + 1];
    int j = low;
    for(int k = 0; k < cache.length; k++)
      cache[k] = new Integer(j++);
 
    // range [-128, 127] must be interned (JLS7 5.1.7)
    assert IntegerCache.high >= 127;
  }
 
  private IntegerCache() {}
}

Integer i1 = 40; 自動裝箱,相當于調用了Integer.valueOf(40);方法。

首先判斷i值是否在-128和127之間,如果在-128和127之間則直接從IntegerCache.cache緩存中獲取指定數字的包裝類;不存在則new出一個新的包裝類。

IntegerCache內部實現了一個Integer的靜態常量數組,在類加載的時候,執行static靜態塊進行初始化-128到127之間的Integer對象,存放到cache數組中。cache屬于常量,存放在java的方法區中。

接著看下面是java8種基本類型的自動裝箱代碼實現。如下:

?
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
//boolean原生類型自動裝箱成Boolean
public static Boolean valueOf(boolean b) {
  return (b ? TRUE : FALSE);
}
 
//byte原生類型自動裝箱成Byte
public static Byte valueOf(byte b) {
  final int offset = 128;
  return ByteCache.cache[(int)b + offset];
}
 
//byte原生類型自動裝箱成Byte
public static Short valueOf(short s) {
  final int offset = 128;
  int sAsInt = s;
  if (sAsInt >= -128 && sAsInt <= 127) { // must cache
    return ShortCache.cache[sAsInt + offset];
  }
  return new Short(s);
}
 
//char原生類型自動裝箱成Character
public static Character valueOf(char c) {
  if (c <= 127) { // must cache
    return CharacterCache.cache[(int)c];
  }
  return new Character(c);
}
 
//int原生類型自動裝箱成Integer
public static Integer valueOf(int i) {
  if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
  return new Integer(i);
}
 
//int原生類型自動裝箱成Long
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);
}
 
//double原生類型自動裝箱成Double
public static Double valueOf(double d) {
  return new Double(d);
}
 
//float原生類型自動裝箱成Float
public static Float valueOf(float f) {
  return new Float(f);
}

通過分析源碼發現,只有double和float的自動裝箱代碼沒有使用緩存,每次都是new 新的對象,其它的6種基本類型都使用了緩存策略。

使用緩存策略是因為,緩存的這些對象都是經常使用到的(如字符、-128至127之間的數字),防止每次自動裝箱都創建一此對象的實例。

而double、float是浮點型的,沒有特別的熱的(經常使用到的)數據的,緩存效果沒有其它幾種類型使用效率高。

下面在看下裝箱和拆箱問題解惑。

?
1
2
3
4
5
6
7
8
9
10
11
12
//1、這個沒解釋的就是true
System.out.println("i=i0\t" + (i == i0)); //true
//2、int值只要在-128和127之間的自動裝箱對象都從緩存中獲取的,所以為true
System.out.println("i1=i2\t" + (i1 == i2)); //true
//3、涉及到數字的計算,就必須先拆箱成int再做加法運算,所以不管他們的值是否在-128和127之間,只要數字一樣就為true
System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));//true
//比較的是對象內存地址,所以為false
System.out.println("i4=i5\t" + (i4 == i5)); //false
//5、同第3條解釋,拆箱做加法運算,對比的是數字,所以為true
System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));//true  
//double的裝箱操作沒有使用緩存,每次都是new Double,所以false
System.out.println("d1=d2\t" + (d1==d2));//false

相信你看到這就應該能明白上面的程序輸出的結果為什么是true,false了,只要掌握原理,類似的問題就迎刃而解了,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.jianshu.com/p/0ce2279c5691?utm_source=tuicool&utm_medium=referral

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91在线视频免费观看 | 国产精品久久久久久婷婷天堂 | 日日草夜夜 | 99精品在线视频观看 | 一级成人欧美一区在线观看 | 久久久久亚洲视频 | 91在线视频福利 | 精品一区二区久久久久久按摩 | 国产精品久久久久网站 | 中文字幕在线看第二 | 精品亚洲夜色av98在线观看 | 亚洲成人精品视频 | 国产九色在线观看 | 91伊人久久 | videos 欧美| 草草久久久 | 欧美毛片免费观看 | 欧美黑人一级 | 久久国产亚洲精品 | 蜜桃网站免费 | 91精品国产综合久久婷婷香蕉 | 最新在线中文字幕 | 成年人免费黄色片 | 精品一区在线视频 | 999精品久久久 | 日韩在线欧美在线 | 日韩高清电影 | 热久久成人 | 国产一区二区三区视频免费 | 亚洲人成网在线观看 | 国产精品久久久久久婷婷天堂 | 日韩视频www| 国产亚洲精品久久午夜玫瑰园 | 免费黄色在线 | 老子午夜影院 | 噜噜噜躁狠狠躁狠狠精品视频 | 黄色片快播 | 久草成人在线 | 国产一级在线观看视频 | 亚洲午夜1000理论片aa | 免费a级毛片永久免费 |