心得:
一週前和一位剛入職阿里螞蟻金融的學長進行了一次會談:總的來講,java學了一個學期,多是急於求成(我身上最大的缺陷),就直接學JAVA的JDBC編程(MYSQL在大二上學期就開始在用了:2002 1064 HY2000 1042 2053等的錯踩到心碎,不過踩坑不怕,重要的是你對MYSQL認識了多少,如今通常也是偷懶,不多寫.sql建表啊等等操做,哈哈哈都是視圖工具Navcat for mysql:須要的同窗能夠了解一下)
我清晰的記得我在學java次日學的多線程,作了一個買麪包的多線程小demo,說實話,如今已經忘的一乾二淨,可能惟一記住的就是sleep()函數了...我的心得:無論學什麼,都得按部就班
學長在「會談」一直在強調基礎,那麼java基礎是什麼呢?一門語言的基礎永遠不會是老師講的那些:類的訪問權限、包的訪問權限,static是一個類靜態變量、怎麼使用import啊等等膚淺到學了和沒學同樣的東西(多是王某愚見....),學長考了我一道題:html
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
我再加一個: java
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()方法是相同的嗎?mysql
5.既然知道自動裝箱和自動拆箱,那麼具體何時發生這種隱式轉化?git
首先是:sql
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;
而且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),在第二個問題裏邊會詳細解釋less
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 }
第二個問題:緩存(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=1; 2 3 Integer b=1; 4 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 }
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 http://www.javashuo.com/article/p-zadlzdgh-ex.html
有一個前輩的博客寫的很靈性:兩句總結完畢
Integer a = 99; //自動裝箱 至關於調用了Integer的valueOf()函數 int b = a;//自動拆箱 調用了intValue()函數
Integer a1=10;
int a2=10;
System.out.println(a2==a1) //true 懂了原理,這題也太簡單了:原理:包裝類和基本類型進行運算時,隱式自動拆箱......
以前寫的:java基本數據類型的博客:
http://www.javashuo.com/article/p-oivaxoaf-bo.html
遺留的問題:
1.移位運算
2.@Native
3.Character類
4.Number類
5.String 類
6.斷言
7.System類