最近一直在總結反思本身, 趁着如今請假在學校上課的空餘時間,從基礎開始從新溫故學習下Java,充實下本身。html
從下圖中,咱們能夠很清晰的看出Java中的類型,其中紅色方框中的是Java的4種基本數據類型:java
下面咱們來詳細講解上圖中的基本類型:數組
1) 在Java中,整數類型共有4種,它們有固定的表述範圍和字段長度,且不受具體的操做系統的影響,保證了Java的跨平臺性緩存
2) Java語言中,整數有三種表現形式,分別是:安全
a. 十進制整數,如 120, -31, 0ide
b. 八進制整數,要求以0開頭(注意這是數字0,不是字母o),如:012,學習
c. 十六進制整數,要求以0x開頭(注意這是數字0,不是字母o),如: 0x12測試
3) Java語言中,默認的整數類型是int類型,聲明long類型的時候,後面必須要加個l(字母L的小寫,不是大寫字母I,也不是數字1)或者L,建議使用大寫L,防止和數字1,大寫字母I混淆,如:30L, 30l編碼
4) Java中四種整數類型的表述範圍:spa
1) 與整數類型同樣,一樣有固定的表述範圍和字段長度,且不受具體的操做系統的影響,保證了Java的跨平臺性
2) Java語言中,浮點類型有兩種表現形式,分別是:
a. 十進制數形式, 如3.14
b. 科學計數法,如,3.14e2, 3.14e-2, -3.14E2
3) Java語言中,默認的浮點數類型是double,聲明float類型的時候,後面必須添加字母f或者F,如3.14F,3.14f
4) Java中兩種浮點類型的表述範圍:
1) 字符類型是用''單引號括起來的單個字符,例如char c = 'w'; char a = '中';
2) Java字符采用Unicode(全球語言統一編碼)編碼,每一個字符佔兩個字節,於是可用16進制編碼形式表示,如:char c = '\u0061'
3) Java中容許使用轉義字符'\'將其後面的字符轉換成其餘含義, 如: char c = '\n'; //表示換行
1) boolean類型的值只有兩種:true, false
2) boolean類型不能夠轉換爲其餘的數據類型
1) boolean不能夠轉換爲其餘的數據類型
2) 整數型,浮點類型,字符型是能夠相互轉換的,轉換時遵照下面的原則:
a. 容量小的類型自動轉換爲大的類型,數據類型按容量大小排序爲:
byte, short, char < int < long <float < double
b. byte, short, char 三種類型間不會相互轉換,他們三者在計算時,首先會轉換爲int類型
c. 容量大的類型在轉換爲小的類型的時候,必須加上強制轉換符,此時可能形成精度下降或者溢出問題
d. 有多種數據類型混合計算的時候,系統首先自動轉換爲容量最大的那個類型再來繼續計算
e. 實數類型默認爲double類型,如, 1.2; 整數類型默認爲int類型,如 1
1) java中基本類型的包裝類的大部分都實現了常量池技術,這些類是Byte,Short,Integer,Long,Character,Boolean,另外兩種浮點數類型的包裝類則沒有實現。
2) Byte,Short,Integer,Long,Character這5種整型的包裝類也只是在對應值小於等於127時纔可以使用對象池
下面咱們主要使用Long類型來進行講解吧。
首先咱們先寫一個測試類:
LongTypeTest.java
1 package com.kevin.basetype; 2 3 public class LongTypeTest { 4 5 public static void main(String[] args) { 6 long longParam = 30L; 7 Long longParam2 = 30L; 8 } 9 }
咱們經過javac命令編譯後,再經過jad命令生成編譯文件來查看編譯信息,以下:
1 // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. 2 // Jad home page: http://www.kpdus.com/jad.html 3 // Decompiler options: packimports(3) annotate 4 // Source File Name: LongTypeTest.java 5 6 package com.kevin.basetype; 7 8 9 public class LongTypeTest 10 { 11 12 public LongTypeTest() 13 { 14 // 0 0:aload_0 15 // 1 1:invokespecial #1 <Method void Object()> 16 // 2 4:return 17 } 18 19 public static void main(String args[]) 20 { 21 long longParam = 30L; 22 // 0 0:ldc2w #2 <Long 30L> 23 // 1 3:lstore_1 24 Long longParam2 = Long.valueOf(30L); 25 // 2 4:ldc2w #2 <Long 30L> 26 // 3 7:invokestatic #4 <Method Long Long.valueOf(long)> 27 // 4 10:astore_3 28 // 5 11:return 29 } 30 }
從第26行,咱們能夠看到,使用包裝類初始化的時候,調用的是Long類中的valueOf方法,下面咱們看看,Long類中的該方法是怎樣的。
1 public static Long valueOf(long l) { 2 final int offset = 128; 3 //當 l >= -128 && l <= 127 時,返回常量池中緩存的數據 4 if (l >= -128 && l <= 127) { // will cache 5 return LongCache.cache[(int)l + offset]; 6 } 7 //不然初始化一個新的Long對象 8 return new Long(l); 9 }
從代碼中看出,當 l 的值小於127的時候,將會調用LongCache.cache()中獲取常量池中的數值。其中,LongCache是一個內部類
1 //Long類中的私有類 2 private static class LongCache { 3 //私有的構造方法,不容許初始化 4 private LongCache(){} 5 //static final類型,它的值在編譯期間將會肯定下來而且被存儲到常量池中 6 static final Long cache[] = new Long[-(-128) + 127 + 1]; 7 //靜態代碼塊,爲cache數組賦值 8 static { 9 for(int i = 0; i < cache.length; i++) 10 cache[i] = new Long(i - 128); 11 } 12 }
其餘Byte,Short,Integer,Long,Character,Boolean都是差很少的,具體就不在此重複講了。
咱們在Double中的valueOf中咱們能夠看到源代碼是這樣子的:
1 public static Double valueOf(double d) { 2 //直接初始化並返回一個Double對象 3 return new Double(d); 4 }
Float亦是如此。
看到這個,估計你們都很奇怪,這個標題到底是什麼意思呢?下面咱們就來說解下:
1) 當short, int, char 的數值小於127大於-128時,編譯器在內存中會使用byte類型來進行記錄。
2) 當short, int, char 的值大於127卻小於 215-1時,編譯器在內存中會使用char類型來進行記錄。
換句話來講,byte, short, int, char四個基本類型,編譯器在內存中將會使用最小的單位去存儲他們的值的內容。
接着咱們先寫個測試類來驗證下:
1 package com.kevin.basetype; 2 3 public class BaseType { 4 5 public static void main(String[] args) { 6 byte bytePram = 10; 7 Byte bytePram2 = 10; 8 9 short shortParam = 40; 10 Short shrotParam2 = 40; 11 12 int intParam = 20; 13 int intParam2 = 20; 14 Integer integerParam = 20; 15 16 long longParam = 30; 17 Long longParam2 = 30L; 18 19 double doubleParam = 20.0; 20 double doubleParam4 = 20.0; 21 Double doubleParam2 = 20.0; 22 Double doubleParam3 = 20.0; 23 24 float floatParam = 20.0f; 25 Float floatParam2 = 20.0f; 26 27 boolean booleanParam = true; 28 Boolean booleanParam2 = true; 29 30 char charParam = 'a'; 31 char charParam2 = 'a'; 32 Character characterParam = 'a'; 33 } 34 }
2)繼續查看編譯信息:
1 // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. 2 // Jad home page: http://www.kpdus.com/jad.html 3 // Decompiler options: packimports(3) annotate 4 // Source File Name: BaseType.java 5 6 package com.kevin.basetype; 7 8 9 public class BaseType 10 { 11 12 public BaseType() 13 { 14 // 0 0:aload_0 15 // 1 1:invokespecial #1 <Method void Object()> 16 // 2 4:return 17 } 18 19 public static void main(String args[]) 20 { 21 byte byte0 = 10; 22 // 0 0:bipush 10 23 // 1 2:istore_1 24 Byte byte1 = Byte.valueOf((byte)10); 25 // 2 3:bipush 10 26 // 3 5:invokestatic #2 <Method Byte Byte.valueOf(byte)> 27 // 4 8:astore_2 28 byte byte2 = 40; 29 // 5 9:bipush 40 30 // 6 11:istore_3 31 Short short1 = Short.valueOf((short)40); 32 // 7 12:bipush 40 33 // 8 14:invokestatic #3 <Method Short Short.valueOf(short)> 34 // 9 17:astore 4 35 byte byte3 = 20; 36 // 10 19:bipush 20 37 // 11 21:istore 5 38 byte byte4 = 20; 39 // 12 23:bipush 20 40 // 13 25:istore 6 41 Integer integer = Integer.valueOf(20); 42 // 14 27:bipush 20 43 // 15 29:invokestatic #4 <Method Integer Integer.valueOf(int)> 44 // 16 32:astore 7 45 long l = 30L; 46 // 17 34:ldc2w #5 <Long 30L> 47 // 18 37:lstore 8 48 Long long1 = Long.valueOf(30L); 49 // 19 39:ldc2w #5 <Long 30L> 50 // 20 42:invokestatic #7 <Method Long Long.valueOf(long)> 51 // 21 45:astore 10 52 double d = 20D; 53 // 22 47:ldc2w #8 <Double 20D> 54 // 23 50:dstore 11 55 double d1 = 20D; 56 // 24 52:ldc2w #8 <Double 20D> 57 // 25 55:dstore 13 58 Double double1 = Double.valueOf(20D); 59 // 26 57:ldc2w #8 <Double 20D> 60 // 27 60:invokestatic #10 <Method Double Double.valueOf(double)> 61 // 28 63:astore 15 62 Double double2 = Double.valueOf(20D); 63 // 29 65:ldc2w #8 <Double 20D> 64 // 30 68:invokestatic #10 <Method Double Double.valueOf(double)> 65 // 31 71:astore 16 66 float f = 20F; 67 // 32 73:ldc1 #11 <Float 20F> 68 // 33 75:fstore 17 69 Float float1 = Float.valueOf(20F); 70 // 34 77:ldc1 #11 <Float 20F> 71 // 35 79:invokestatic #12 <Method Float Float.valueOf(float)> 72 // 36 82:astore 18 73 boolean flag = true; 74 // 37 84:iconst_1 75 // 38 85:istore 19 76 Boolean boolean1 = Boolean.valueOf(true); 77 // 39 87:iconst_1 78 // 40 88:invokestatic #13 <Method Boolean Boolean.valueOf(boolean)> 79 // 41 91:astore 20 80 byte byte5 = 97; 81 // 42 93:bipush 97 82 // 43 95:istore 21 83 byte byte6 = 97; 84 // 44 97:bipush 97 85 // 45 99:istore 22 86 Character character = Character.valueOf('a'); 87 // 46 101:bipush 97 88 // 47 103:invokestatic #14 <Method Character Character.valueOf(char)> 89 // 48 106:astore 23 90 // 49 108:return 91 } 92 }
看完上面之後,你們可能會有這麼一個疑問:short, char都是兩個字節,爲何存儲的時候,會選擇使用char類型來進行存儲二不選擇short呢?
解答:由於short是有符號的,而char類型是無類型的,能夠表示的數值範圍比short大,因此雖然一樣是兩個字節,可是卻選擇了char類型而不選擇short類型進行值存儲。
1) 全部的基本類型的包裝類都使用了final來進行修飾,保證了系統的安全性,試想一下,假設有人也自定義了這麼一個java.lang.Integer同時繼承了jdk中的java.lang.Integer,而且在裏面實現了一些破壞性的代碼,那後果將不堪設想了對吧。
2) 除了Character,Boolean之外,其餘的基本類型包裝類都繼承了抽象類Number。這個抽象類要求繼承類必須實現將當前類型的值轉換爲其餘類型的值方法
3)全部的基本類型包裝類都實現了接口Comparable。這個接口的做用是:
a. 當List/Array中的對象實現了該接口的話,能夠直接用Collections.sort()方法進行自動排序
b. 當一個普通的Object對象實現了該接口,那麼將能夠用做具備自動sort做用(例如TreeMap)的Map集合中的排序依據key或者具備自動sort做用的Set集合中的排序根據對象