學習java的同學注意了!!! 學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:523047986 我們一起學Java!
一、數據類型
從下圖中,我們可以很清晰的看出Java中的類型,其中紅色方框中的是Java的4種基本數據類型:
下面我們來詳細講解上圖中的基本類型:
1.整數類型
1) 在Java中,整數類型共有4種,它們有固定的表述范圍和字段長度,且不受具體的操作系統的影響,保證了Java的跨平臺性
2) Java語言中,整數有三種表現形式,分別是:
a. 十進制整數,如 120, -31, 0
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中四種整數類型的表述范圍:
2.浮點類型
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中兩種浮點類型的表述范圍:
3. 字符類型
1) 字符類型是用''單引號括起來的單個字符,例如char c = 'w'; char a = '中';
2) Java字符采用Unicode(全球語言統一編碼)編碼,每個字符占兩個字節,因而可用16進制編碼形式表示,如:char c = '/u0061'
3) Java中允許使用轉義字符'/'將其后面的字符轉換成其他含義, 如: char c = '/n'; //表示換行
4.布爾類型
1) boolean類型的值只有兩種:true, false
2) boolean類型不可以轉換為其他的數據類型
5.基本數據類型的轉換
1) boolean不可以轉換為其他的數據類型
2) 整數型,浮點類型,字符型是可以相互轉換的,轉換時遵守下面的原則:
a. 容量小的類型自動轉換為大的類型,數據類型按容量大小排序為:
byte, short, char < int < long <float < double
b. byte, short, char 三種類型間不會相互轉換,他們三者在計算時,首先會轉換為int類型
c. 容量大的類型在轉換為小的類型的時候,必須加上強制轉換符,此時可能造成精度降低或者溢出問題
d. 有多種數據類型混合計算的時候,系統首先自動轉換為容量最大的那個類型再來繼續計算
e. 實數類型默認為double類型,如, 1.2; 整數類型默認為int類型,如 1
二、JVM對基本類型的處理
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 LongTypeTest10 {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 cache5 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亦是如此。
2.short, int, char -> byte(char)
看到這個,估計大家都很奇怪,這個標題究竟是什么意思呢?下面我們就來講解下:
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 BaseType10 {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 1023 // 1 2:istore_1 24 Byte byte1 = Byte.valueOf((byte)10);25 // 2 3:bipush 1026 // 3 5:invokestatic #2 <Method Byte Byte.valueOf(byte)>27 // 4 8:astore_2 28 byte byte2 = 40;29 // 5 9:bipush 4030 // 6 11:istore_3 31 Short short1 = Short.valueOf((short)40);32 // 7 12:bipush 4033 // 8 14:invokestatic #3 <Method Short Short.valueOf(short)>34 // 9 17:astore 435 byte byte3 = 20;36 // 10 19:bipush 2037 // 11 21:istore 538 byte byte4 = 20;39 // 12 23:bipush 2040 // 13 25:istore 641 Integer integer = Integer.valueOf(20);42 // 14 27:bipush 2043 // 15 29:invokestatic #4 <Method Integer Integer.valueOf(int)>44 // 16 32:astore 745 long l = 30L;46 // 17 34:ldc2w #5 <Long 30L>47 // 18 37:lstore 848 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 1052 double d = 20D;53 // 22 47:ldc2w #8 <Double 20D>54 // 23 50:dstore 1155 double d1 = 20D;56 // 24 52:ldc2w #8 <Double 20D>57 // 25 55:dstore 1358 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 1562 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 1666 float f = 20F;67 // 32 73:ldc1 #11 <Float 20F>68 // 33 75:fstore 1769 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 1873 boolean flag = true;74 // 37 84:iconst_1 75 // 38 85:istore 1976 Boolean boolean1 = Boolean.valueOf(true);77 // 39 87:iconst_1 78 // 40 88:invokestatic #13 <Method Boolean Boolean.valueOf(boolean)>79 // 41 91:astore 2080 byte byte5 = 97;81 // 42 93:bipush 9782 // 43 95:istore 2183 byte byte6 = 97;84 // 44 97:bipush 9785 // 45 99:istore 2286 Character character = Character.valueOf('a');87 // 46 101:bipush 9788 // 47 103:invokestatic #14 <Method Character Character.valueOf(char)>89 // 48 106:astore 2390 // 49 108:return 91 }92 }看完上面以后,大家可能會有這么一個疑問:short, char都是兩個字節,為什么存儲的時候,會選擇使用char類型來進行存儲二不選擇short呢?
解答:因為short是有符號的,而char類型是無類型的,可以表示的數值范圍比short大,所以雖然同樣是兩個字節,但是卻選擇了char類型而不選擇short類型進行值存儲。
3.final, Number, Comparable與基礎類型包裝類的關系
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集合中的排序根據對象
學習Java的同學注意了!!! 學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:523047986 我們一起學Java!
新聞熱點
疑難解答