Java源碼解讀(一) 8種基本類型對應的封裝類型
阿新 • • 發佈:2018-01-20
高精度 ria font sts ack mil 不能 F12 比較
2、自動轉型等級:byte,short,char(同級)-> int -> long -> float -> double (由低精度到高精度),同級不能自動轉型,需要強制轉換
說起源碼其實第一個要看的應該是我們的父類Object,這裏就不對它進行描述了大家各自對其進行閱讀即可。
一、八種基本類型
接下來介紹我們的八種基本類型(這個大家都知道吧):char、byte、short、int、long、float、double、boolean。這裏也不太描述其過多的東西,只說些要特別註意的事項(如果我這存在遺落的,歡迎大家補充):
1、byte、short、char 不能進行含有變量的運算符運算(正常的運算符),都要求進行強轉,因為都有範圍限制。 但是可以進行+= 和自增增減的操作。2、自動轉型等級:byte,short,char(同級)-> int -> long -> float -> double (由低精度到高精度),同級不能自動轉型,需要強制轉換
二、八種封裝類型
先說共同點:
- equals方法:
public boolean equals(Object obj) { if (obj instanceof Short) { return value == ((Short)obj).shortValue(); } return false; }所以不同類型的不管值是否相等都是false;
@Test public voidtestEquals(){ Short num1 = 1; Integer num2 = 1; Long num3 = 1L; System.out.println(num1.equals(num2));//false System.out.println(num2.equals(num3));//false }
- 直接賦值時,都會調用valueOf方法。所以要註意其的源代碼。
- 註意valueOf中代碼,它緩存了ASCII碼0~127的字符。其他均會創建實例。
2、Byte
- 範圍是-128~127,所以超過這個範圍會要求強制轉換。如果使用Byte(String s)創建實例的話,超過範圍會拋出異常:NumberFormatException
- 註意valueOf中的代碼,它緩存了-128~127,所以直接賦值是不創建新實例的。
@Test public void testByte(){ //byte的範圍是-128~127,針對byte如果賦值不在範圍eclipse會要求強制轉型成byte. //封裝類型Byte new Byte("128")當使用字符串創建實例時,其中值超過範圍會報錯NumberFormatException。 byte b1 = 12; Byte b2 = 12;//(byte)129;//超過範圍要求強轉 Byte b3 = 12;//(byte)129; //Byte b4 = new Byte("128");//拋出異常 Byte b4 = new Byte("12");//拋出異常 System.out.println(b1 == b2);//true System.out.println(b2 == b3);//true System.out.println(b2 == b4);//false }3、Short
- 跟byte的第一點一樣,只是範圍(-32768 ~ 32767)不一樣
- 註意valueOf方法,它緩存了-128~127的值,超過這個範圍(-128~127)就會創建新的實例。
- 基於第二種情況,不便於進行循環遍歷復制操作,否則超過範圍就會多個實例,影響內存。
@Test public void testShort(){ //1、short範圍:-32768 ~ 32767 Short s = new Short("32767");//超過範圍會報錯 NumberFormatException s = new Short((short)327671);//超過這個範圍自動轉換 //2、裝箱與拆箱 自動轉型 short s1 = 12; Short s2 = new Short(s1);//手動裝箱 System.out.println("s1 == s2:" + (s1 == s2));//自動拆箱 true //3、valueOf方法緩存了-128~127的範圍,超過這個範圍就要另外創建這個實例。 Short s3 = 12; Short s4 = 12; Short s5 = 128; Short s6 = 128; System.out.println("s3 == s4:" + (s3 == s4)); //true System.out.println("s5 == s6:" + (s5 == s6)); //false //4、由於上面這個特性,所以這種包裝類型不能在循環遍歷中賦值。不然其值超過這個範圍的話,就會創建新的對象,如果很多的話,就會創建很多對象。浪費空間。 }4、Integer
- 承受的值要註意範圍(-2147483648 ~ 2147483647 ),不要求強轉。
- 註意valueOf方法,跟Short的方法一樣,緩存了-128~127的值,超過這個範圍(-128~127)就會創建新的實例。
- 基於第二種情況,不便於進行循環遍歷復制操作,否則超過範圍就會多個實例,影響內存。
@Test public void testInteger(){ //1、Integer範圍:-2147483648 ~ 2147483647 //後面與Short一樣 //2、裝箱與拆箱 自動轉型 int s1 = 12; Integer s2 = new Integer(s1);//手動裝箱 System.out.println("s1 == s2:" + (s1 == s2));//自動拆箱 true //3、valueOf方法緩存了-128~127的範圍,超過這個範圍就要另外創建這個實例。 Integer s3 = 12; Integer s4 = 12; Integer s5 = 128; Integer s6 = 128; System.out.println("s3 == s4:" + (s3 == s4));//true System.out.println("s5 == s6:" + (s5 == s6));//false //4、由於上面這個特性,所以這種包裝類型不能在循環遍歷中賦值。不然其值超過這個範圍的話,就會創建新的對象,如果很多的話,就會創建很多對象。浪費空間。 }
- 承受的值要註意範圍(-9223372036854775808 ~ 9223372036854775807 ),不要求強轉。
- 註意valueOf方法,跟Short的方法一樣,緩存了-128~127的值,超過這個範圍(-128~127)就會創建新的實例。
- 基於第二種情況,不便於進行循環遍歷復制操作,否則超過範圍就會多個實例,影響內存。
@Test public void testLong(){ //範圍就不考慮了。 //同樣、valueOf方法緩存了-128~127的範圍,超過這個範圍就要另外創建這個實例。 Long s3 = 12L; Long s4 = 12L; Long s5 = 128L; Long s6 = 128L; System.out.println("s3 == s4:" + (s3 == s4));//true System.out.println("s5 == s6:" + (s5 == s6));//false //由於上面這個特性,所以這種包裝類型不能在循環遍歷中賦值。不然其值超過這個範圍的話,就會創建新的對象,如果很多的話,就會創建很多對象。浪費空間。 }
- 承受的值要註意範圍(-1.4E-45~ 3.4028235E38),不要求強轉。
- 註意valueOf方法,跟前面的Short、Integer、Long不一樣了,直接創建實例。
- 所以相等值的兩個變量 ==運算是false.
- 不要做加減法運算。精度(9位)問題。
@Test public void testFloat(){ //沒有特殊要註意的,其他跟上面一樣 int f = 1; Float f1 = 1F; Float f2 = new Float(f); System.out.println(f == f1);//true System.out.println(f1 == f2);//false //註意不要用這類型做加減運算,精度問題會影響。 System.out.println(f1 - 0.1f*9);//0.099999964 }7、Double
- 承受的值要註意範圍,不要求強轉。
- 註意valueOf方法,與float一樣,直接創建實例。
- 不要做加減法運算。精度(17位)問題。
@Test public void testDouble(){ //註意不要用這類型做加減運算,精度問題會影響。 System.out. println(1.0 - 0.1*9);//0.09999999999999998 //valueof Double i1 = 100.0; Double i2 = 100.0; Double i3 = 200.0; Double i4 = 200.0; System.out.println(i1==i2);//false System.out.println(i3==i4);//false }8、Boolean
- valueof方法
緩存了兩個方法,所以如果是同樣的賦值,== 運算是為true的。
@Test public void testEquals(){ Short num1 = 1; Integer num2 = 1; Long num3 = 1L; System.out.println(num1.equals(num2));//false System.out.println(num2.equals(num3));//false }
三、案例分析
猜猜下面各個輸出的結果是什麽:
@Test public void test1(){ Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L; System.out.println(c==d); System.out.println(e==f); System.out.println(c==(a+b)); System.out.println(c.equals(a+b)); System.out.println(g==(a+b)); System.out.println(g.equals(a+b)); System.out.println(g.equals(a+h)); }
其中會涉及到拆箱與裝箱(自行弄懂)的問題。針對個別解析如下:
c==(a+b) :a+b都會拆箱成int然後相加,所以c也會自動拆箱比較。
g==(a+b):同理,a+b都會拆箱成int然後相加,g會拆箱成long類型。所以基本類型比較只要比較其值即可。
g.equals(a+b):先拆箱a+b再裝箱還是Integer,這裏不會自動轉型。Long類型的equals判斷不是同一類型直接返回false
g.equals(a+h):同上,先拆箱a+h再裝箱(這裏會自動向上轉型)為Long,所以同類型的比較值又相等,這裏返回true.
最終結果如下:
true false true true true false true
Java源碼解讀(一) 8種基本類型對應的封裝類型