一、Java的基本類型
Java語言中提供了八種基本類型,包括六種數字類型(四個整數型,兩個浮點型),一種字符類型,還有一種布爾型。
- 整數型,包括byte、short、int、long,默認初始值是0;
- 浮點型,包括float、double,默認初始值是0.0;
- 字符型,char型,默認值是'',注意跟“”的區別,''是字符的引號,“”是字符串的引號,兩者不同。
- 布爾型,boolean,默認初始值是false。
注意:如果不初始化一個char類型的變量,將它輸出在console的時候你看不到任何結果。Java中,字符型並不是用ASCII碼來存儲的,而是用16位的Unicode字符集來存儲,它的范圍就是字符集的范圍,默認值是u000000。
二、包裝類
包裝類把基本類型轉換為對象,每個基本類型在java.lang包中都有一個相應的包裝類,包括有:
基本類型 | 包裝類型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
此外,在java.math包中還有兩個用於數字計算的類型,分別是BigInteger、BigDecimal。它們無對應的基本類型,主要應用於高精度的運算,其中BigInteger 支持任意精度的整數運算,BigDecimal支持任意精度帶小數點的運算,可以用於避免使用基本類型時產生的精度損失等問題。
三、包裝類的用法
這里只討論六種數字基本類型對應的包裝類,因為它們是使用最頻繁的,這些類中常用的方法可分為兩類:一種是本類型與其它基本類型之間的轉換,另一種是字符串與本類型和基本類型之間的轉換。如下圖,是Integer類中的一些常用方法:
其中的前五個,都是屬於第一種,即與其它基本類型之間的轉換。下面的三個則屬於第二種,是字符串與本類型及基本類型之間的轉換。
A、本類型與其它類型轉換
示例如下:
1 Integer temp1 = new Integer(45); 2 int temp2 = 45; 3 4 byte t1 = temp1.byteValue(); //包裝類的轉換 5 byte t2 = (byte)temp2; //基本數據類型的強制類型轉換
B、本類型和對應基本類型轉換
JDK1.5引入了自動裝箱和拆箱的機制,那么什么是裝箱和拆箱呢?
裝箱就是將基本類型轉換成包裝類,分為自動裝箱和手動裝箱。同樣地,拆箱就是將包裝類型轉換成基本類型,也分為自動拆箱和手動拆箱。
示例如下:
1 int a1=4; 2 3 //手動裝箱 4 Integer aI1 = new Integer(a1); 5 //自動裝箱 6 Integer aI2 = a1; 7 8 //手動拆箱 9 int ai1 = aI1.intValue(); 10 //自動拆箱 11 int ai2 = aI2;
C、字符串和基本類型轉換
c1.基本類型轉換成字符串類型
c1a. 包裝類 的toString()方法
c1b. String 類的valueOf()方法
c1c. 空字符串加一個基本類型變量
1 //基本類型轉換成字符串類型有三種方法 2 int b = 1; 3 String b1 = Integer.toString(b); 4 String b2 = String.valueOf(b); 5 String b3 = b+""; 6 System.out.println("b1: "+b1+"b2: "+b2+"b3: "+b3);
c2.字符串轉換成基本類型
c2a. 包裝類的parse***()靜態方法
c2b. 包裝類的valueOf()方法
//字符串轉換成基本類型的方法有兩種 String b = "121"; int c1 = Integer.parseInt(b); int c2 = Integer.valueOf(b);
四、基本類型和包裝類的異同
4.1 在Java中,一切皆對象,但八大基本類型卻不是對象。
4.2 聲明方式的不同,基本類型無需通過new關鍵字來創建,而包裝類型需new關鍵字。
4.3 存儲方式及位置的不同,基本類型是直接存儲變量的值保存在堆棧中,能高效的存取,包裝類型需要通過引用指向實例,具體的實例保存在堆中。
4.4 初始值的不同,包裝類型的初始值為null,基本類型的的初始值視具體的類型而定。
4.5 使用方式的不同,如與集合類合作使用時只能使用包裝類型。
五、Integer與int數據的比較
在Java中,因為有自動裝箱/拆箱操作,所以int與Integer類型在比較大小時基本是沒有差別的。
利用一段程序驗證如下:
public class TestInteger { public static void main(String[] args) { int t1 = 46; int t2 = 46; Integer t3 = 46; Integer t4 = new Integer(46); Integer t5 = t1; Integer t6 = new Integer(t2); System.out.println("t1 == t2 " + (t1 == t2)); System.out.println("t1 == t3 " + (t1 == t3)); System.out.println("t1 == t4 " + (t1 == t4)); System.out.println("t1 == t5 " + (t1 == t5)); System.out.println("t1 == t6 " + (t1 == t6)); System.out.println("t4 == t2 " + (t4 == t2)); System.out.println("t5 == t2 " + (t5 == t2)); System.out.println("t6 == t2 " + (t6 == t2)); System.out.println("t4 == t3 " + (t4 == t3)); System.out.println("t5 == t3 " + (t5 == t3)); System.out.println("t6 == t3 " + (t6 == t3)); System.out.println("t3 equals t4 " + (t3.equals(t4))); System.out.println("t3 equals t5 " + (t3.equals(t5))); System.out.println("t3 equals t6 " + (t3.equals(t6))); System.out.println("t3 equals t4 " + (t3.equals(t4))); System.out.println("t4 equals t5 " + (t4.equals(t5))); System.out.println("t4 equals t6 " + (t4.equals(t6))); System.out.println("t5 equals t6 " + (t5.equals(t6))); } }
上面的程序中,分別利用針對變量和具體數字的兩種裝箱方式定義了四個Integer類的變量,
在后續的測試代碼中分別使用了==和equals兩種方式進行比較,其輸出結果為:
t1 == t2 true
t1 == t3 true
t1 == t4 true
t1 == t5 true
t1 == t6 true
t4 == t2 true
t5 == t2 true
t6 == t2 true
t4 == t3 false
t5 == t3 true
t6 == t3 false
t3 equals t4 true
t3 equals t5 true
t3 equals t6 true
t3 equals t4 true
t4 equals t5 true
t4 equals t6 true
t5 equals t6 true
使用equals方式的比較中,所有的結果都是true。Integer類中的equals方法具體是:
1 public boolean equals(Object obj) { 2 if (obj instanceof Integer) { 3 return value == ((Integer)obj).intValue(); 4 } 5 return false; 6 }
從代碼可以看出,兩個Integer類的equals方法最終比較的是,其各自所包裝的intValue的值是否相等,因此,所有的輸出結果都是true。
在使用==比較的時候,輸出結果中有兩個是false,都是在兩個Integer類比較時產生的。因為當==比較的一個Integer類和一個int變量時,自動裝箱/拆箱會對其進行處理,最終比較的是數值結果。當面對兩個Integer類時,==所比較的是兩個引用所指的是否為同一對象。而在上面的程序中,t4和t6都是通過new創建出的新對象,因此它們與前面的t3是完全不同的引用,所以結果是false。
值得注意的是t3和t5的比較結果,針對數值46和int變量t1的自動裝箱結果指向的是同一個Integer對象,這說明在這段程序中,沒有使用new來顯式創建新對象時,虛擬機只會將引用指向已經存在的結果。