java Integer與int詳解 01


心得:
一周前和一位剛入職阿里螞蟻金融的學長進行了一次會談:總的來說,java學了一個學期,可能是急於求成(我身上最大的缺陷),就直接學JAVA的JDBC編程(MYSQL在大二上學期就開始在用了:2002 1064 HY2000 1042 2053等的錯踩到心碎,不過踩坑不怕,重要的是你對MYSQL認識了多少,現在一般也是偷懶,很少寫.sql建表啊等等操作,哈哈哈都是視圖工具Navcat for mysql:需要的同學可以了解一下)
我清晰的記得我在學java第二天學的多線程,做了一個買面包的多線程小demo,說實話,現在已經忘的一干二凈,可能唯一記住的就是sleep()函數了...個人心得:不管學什么,都得循序漸進
學長在“會談”一直在強調基礎,那么java基礎是什么呢?一門語言的基礎永遠不會是老師講的那些:類的訪問權限、包的訪問權限,static是一個類靜態變量、怎么使用import啊等等膚淺到學了和沒學一樣的東西(可能是王某愚見....),學長考了我一道題:

   Integer a=200;
   Integer b=200;
   Integer a1=2;
   Integer b1=2;
   System.out.println(a==b); //false   1
   System.out.println(a1==b1); //true  2


我再加一個:   

1   Integer c=new Integer(200);
2   Integer d=new Integer(200);
3   System.out.println(c==d); //false    3


很簡單:我很快就說出了正確答案,但學長的問題來了:
  1.Integer對象和int數據類型的區別是什么?
  2.既然知道緩存,那么緩存到了哪里?為什么緩存?Integer、int的適用場景分別是什么?
  3.System.out.println(a.equals(b)); //true 為什么? integer既然繼承自Object,那么你能說一下Object都有什么方法嗎?
  4.不同類型的equals()方法是相同的嗎?

  5.既然知道自動裝箱和自動拆箱,那么具體什么時候發生這種隱式轉化?

 

首先是:

public final class Integer extends Number implements Comparable<Integer> {}
   //Integer 的類聲明,第一句要注意三個點:Number類了解多少?Comparable<T>泛型比較接口了解多少?CompareTo()函數的實現原則?


  問題一:
   Integer 是int的包裝類,在Integer對象里邊包含了一個int基本類型的私有屬性值

1     /**
2      * The value of the {@code Integer}.
3      *
4      * @serial
5      */
6     private final int value;
View Code

  並且Integer也提供了很多供我們使用的方法:
   我們從構造函數說起:
   1>.向構造函數傳int值
  

public Integer(int value) {
        this.value = value; //為value賦值
    }


   也就是說,Integer c=new Integer(200);  這一行相當於是Integer對象里面的私有屬性value的賦值

  2> Integer i=2;

  經過斷點測試: 這一句代碼會調用Integer的一個函數:ValueOf() 涉及到緩存(IntegerCache),在第二個問題里邊會詳細解釋

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

還有很多ValueOf()的重載函數:基本上都是parseInt()函數的調用

1    public static Integer valueOf(String s, int radix) throws   NumberFormatException {
2         return Integer.valueOf(parseInt(s,radix));
3     }
4     public static Integer valueOf(String s) throws NumberFormatException {
5         return Integer.valueOf(parseInt(s, 10));
6     }

 


  3> 向構造函數傳String字符串

 1 public Integer(String s) throws NumberFormatException {
 2         this.value = parseInt(s, 10); //10為進制
 3     }
 4     public static int parseInt(String s, int radix)
 5                 throws NumberFormatException   //數字格式異常
 6     {
 7 
 8         if (s == null) {
 9             throw new NumberFormatException("null");
10         }
11 
12         if (radix < Character.MIN_RADIX) { //java.lang.Character了解多少 13             throw new NumberFormatException("radix " + radix +
14                                             " less than Character.MIN_RADIX");
15         }
16 
17         if (radix > Character.MAX_RADIX) {
18             throw new NumberFormatException("radix " + radix +
19                                             " greater than Character.MAX_RADIX");
20         }
21 
22         int result = 0;
23         boolean negative = false;
24         int i = 0, len = s.length();
25         int limit = -Integer.MAX_VALUE;   //@Native public static final int MAX_VALUE = 0x7fffffff; @Native 了解多少? 26         int multmin;
27         int digit;
28 
29         if (len > 0) { //不為空 30             char firstChar = s.charAt(0); //String類的操作方法了解多少 31             if (firstChar < '0') { // Possible leading "+" or "-"   '-'<'0'&&'+'<'0' true ASCLL碼的比較 ‘1’<'0' 數據類型的自動轉化 (String)‘1’=》(int)1 
 32                 if (firstChar == '-') {
33                     negative = true;  //是一個負數 34                     limit = Integer.MIN_VALUE;
35                 } else if (firstChar != '+')
36                     throw NumberFormatException.forInputString(s);
37 
38                 if (len == 1) // Cannot have lone "+" or "-"
39                     throw NumberFormatException.forInputString(s);
40                 i++; 
41             }
42             multmin = limit / radix; 
43             while (i < len) {
44                 // Accumulating negatively avoids surprises near MAX_VALUE
45                 digit = Character.digit(s.charAt(i++),radix);  //java.lang.Character.digit()方法用法 : 在指定的基數(radix)返回字符ch的數值 //Character.digit('0',10)=0; Character.digit('a',10);=-1 46                 if (digit < 0) {
47                     throw NumberFormatException.forInputString(s);
48                 }
49                 if (result < multmin) {
50                     throw NumberFormatException.forInputString(s);
51                 }
52                 result *= radix; //數值進位制的變化 53                 if (result < limit + digit) {  //結果如果小於所能表示的最小值 54                     throw NumberFormatException.forInputString(s);
55                 }
56                 result -= digit;
57             }
58         } else {
59             throw NumberFormatException.forInputString(s);
60         }
61         return negative ? result : -result;
62     }

 4>Integer的ToString()實現(移位運算沒看懂......)

 final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };


public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(buf, true); }
static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) //本人覺得這里是一個非常巧妙的設計 return i+1; } static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // Generate two digits per iteration while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); //????這個為什么是52429我也不知道......但是如果你打幾個斷點...看看結果還是能看懂的....hhh r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { buf [--charPos] = sign; } }

 當然還有很多函數,比如:

public static Integer getInteger(String nm, Integer val):返回具有指定名稱的系統屬性的整數值:注意是返回一個系統屬性的屬性值,

問題又來了:System 系統類了解多少???(走到哪里都會引發一堆一堆的問題.....最后一定要總結),我就給大家粘貼一下代碼吧:

 1  public static Integer getInteger(String nm, int val) {
 2         Integer result = getInteger(nm, null);
 3         return (result == null) ? Integer.valueOf(val) : result;
 4     }
 5 
 6     public static Integer getInteger(String nm, int val) {
 7         Integer result = getInteger(nm, null);
 8         return (result == null) ? Integer.valueOf(val) : result;
 9     }
10 
11 
12 
13 public static Integer getInteger(String nm, Integer val) {
14         String v = null;
15         try {
16             v = System.getProperty(nm);
17         } catch (IllegalArgumentException | NullPointerException e) {
18         }
19         if (v != null) {
20             try {
21                 return Integer.decode(v);
22             } catch (NumberFormatException e) {
23             }
24         }
25         return val;
26     }
27  public static Integer decode(String nm) throws NumberFormatException {
28         int radix = 10;
29         int index = 0;
30         boolean negative = false;
31         Integer result;
32 
33         if (nm.length() == 0)
34             throw new NumberFormatException("Zero length string");
35         char firstChar = nm.charAt(0);
36         // Handle sign, if present
37         if (firstChar == '-') {
38             negative = true;
39             index++;
40         } else if (firstChar == '+')
41             index++;
42 
43         // Handle radix specifier, if present
44         if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
45             index += 2;
46             radix = 16;
47         }
48         else if (nm.startsWith("#", index)) {
49             index ++;
50             radix = 16;
51         }
52         else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
53             index ++;
54             radix = 8;
55         }
56 
57         if (nm.startsWith("-", index) || nm.startsWith("+", index))
58             throw new NumberFormatException("Sign character in wrong position");
59 
60         try {
61             result = Integer.valueOf(nm.substring(index), radix);
62             result = negative ? Integer.valueOf(-result.intValue()) : result;
63         } catch (NumberFormatException e) {
64             // If number is Integer.MIN_VALUE, we'll end up here. The next line
65             // handles this case, and causes any genuine format error to be
66             // rethrown.
67             String constant = negative ? ("-" + nm.substring(index))
68                                        : nm.substring(index);
69             result = Integer.valueOf(constant, radix);
70         }
71         return result;
72     }
View Code

 第二個問題:緩存(IntegerCache)先上代碼:

 1  private static class IntegerCache {
 2         static final int low = -128;
 3         static final int high;
 4         static final Integer cache[];
 5 
 6         static {
 7             // high value may be configured by property  high的值可能取決於不同的操作系統,
//據查閱:在jav5之前,緩存范圍是寫死在-128-127之間的,但是在 Java 6 中,
//最大值映射到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的啟動參數設置最大值。
//這使我們可以根據應用程序的實際情況靈活地調整來提高性能,
8 int h = 127; 9 String integerCacheHighPropValue = 10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
//之前一直認為Integer是緩存在JVM里邊的,原來是自己沒有充分認識到JVM、JDK、JRE的真正區別。
//查閱資料后,Integer是緩存在JDK里的.....雖然現在也不是很理解
String a = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//???
我嘗試了一下,疑惑加一
//String b = sun.misc.VM.getSavedProperty("high"); =》null
//String c = System.getProperty("java.lang.Integer.IntegerCache.high"); =》null
//String d = System.getProperty("high"); =》null?????
11 if (integerCacheHighPropValue != null) { 12 try { 13 int i = parseInt(integerCacheHighPropValue); 14 i = Math.max(i, 127); 15 // Maximum array size is Integer.MAX_VALUE 16 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 17 } catch( NumberFormatException nfe) { 18 // If the property cannot be parsed into an int, ignore it. 19 } 20 } 21 high = h; 22 23 cache = new Integer[(high - low) + 1]; 24 int j = low; 25 for(int k = 0; k < cache.length; k++) 26 cache[k] = new Integer(j++); 27 28 // range [-128, 127] must be interned (JLS7 5.1.7) 29 assert IntegerCache.high >= 127; //斷言了解多少? 30 } 31 32 private IntegerCache() {} 33 }

了解了IntegerCache緩存類:再來看ValueOf函數()

 

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

 

1 Integer a=12 
3 Integer b=14 
5 Integer c=200
7 Integer d=200;

 

調用valueOf函數之后,確定i是否在緩存范圍內,如果在,返回已經緩存下來的,如果不在,就返回一個新的Integer對象

故:a和b其實指向的是同一個Integer對象,c和d返回兩個 堆地址不同的但是value相同的Integer對象。

引用類型存在堆中,基本類型與引用存在棧中,這是再基本不過的操作...

補充:

這種緩存行為不僅適用於Integer對象。我們針對所有整數類型的類都有類似的緩存機制。
有 ByteCache 用於緩存 Byte 對象
有 ShortCache 用於緩存 Short 對象
有 LongCache 用於緩存 Long 對象
有 CharacterCache 用於緩存 Character 對象
Byte,Short,Long 有固定范圍: -128 到 127。對於 Character, 范圍是 0 到 127。除了 Integer 可以通過參數改變范圍外,其它的都不行


  第三個問題:equals()函數

/**
     * Returns the value of this {@code Integer} as an
     * {@code int}.
     */
    public int intValue() {
        return value;
    }
1  public boolean equals(Object obj) {
2         if (obj instanceof Integer) {
3             return value == ((Integer)obj).intValue();
4         }
5         return false;
6     }
7
8 Integer a=200;
9 Integer b=200;
10 a.equals(b) //true 實際比較的是包裝類中的value值,(int)200和(int)200必定會相等,這就解決了緩存帶來的差異

接下來我將貼幾個equals():

String類的

 1  public boolean equals(Object anObject) {
 2         if (this == anObject) {
 3             return true; //棧里指向堆的地址相同==引用指向通過一個對象
 4         }
 5         if (anObject instanceof String) {
 6             String anotherString = (String)anObject;
 7             int n = value.length;
 8             if (n == anotherString.value.length) {
 9                 char v1[] = value;
10                 char v2[] = anotherString.value;
11                 int i = 0;
12                 while (n-- != 0) {
13                     if (v1[i] != v2[i])
14                         return false; //char數組的依次比較,String中的value又是什么呢?
15                     i++;
16                 }
17                 return true;
18             }
19         }
20         return false;
21     }
1 public final class String
2     implements java.io.Serializable, Comparable<String>, CharSequence {
3     /** The value is used for character storage. */
4     private final char value[];
5  ......
6 }
View Code

Object 的equals()

1  public boolean equals(Object obj) {
2         return (this == obj);
3     }

Object作為所有對象的直接父類...大多數的對象都是要重寫equals函數;

第四個問題:Object的函數:
這個我本來就知道toString()、hasCode()、equals()、clone();

但是通過看了看源碼:發現Thread類繼承自Object,所以必然會有有關線程的函數...那么問題來了...run()、sleep()又是哪里來的????

public final native void notify();

public final native void notifyAll();

public final native void wait(long timeout) throws InterruptedException;

第五個問題:autoboxing、unboxing https://www.cnblogs.com/wang-yaz/p/8516151.html

有一個前輩的博客寫的很靈性:兩句總結完畢

 Integer a = 99; //自動裝箱 相當於調用了Integer的valueOf()函數
 int b = a;//自動拆箱 調用了intValue()函數

Integer a1=10;
int a2=10;
System.out.println(a2==a1) //true 懂了原理,這題也太簡單了:原理:包裝類和基本類型進行運算時,隱式自動拆箱......

之前寫的:java基本數據類型的博客:
   https://www.cnblogs.com/laiso/p/8672524.html

遺留的問題:

1.移位運算

2.@Native

3.Character類

4.Number類

5.String 類

6.斷言

7.System類

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM