Java 提供兩種不一樣的類型:引用類型和原始類型(或內置類型)。另外,Java 還爲每一個原始類型提供了封裝類(Wrapper)。若是須要一個整型變量,是使用基本的 int 型呢,仍是使用 Integer 類的一個對象呢?若是須要聲明一個布爾類型,是使用基本的 boolean,仍是使用 Boolean 類的一個對象呢?本文可幫助您做出決定。java
下表列出了原始類型以及它們的對象封裝類。程序員
原始類型 | 封裝類 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long 數據結構 |
Long |
float | Float |
double | Double |
引用類型和原始類型的行爲徹底不一樣,而且它們具備不一樣的語義。例如,假定一個方法中有兩個局部變量,一個變量爲 int 原始類型,另外一個變量是對一個 Integer 對象的對象引用:app
int i = 5; // 原始類型 Integer j = new Integer(10); // 對象引用
這兩個變量都存儲在局部變量表中,而且都是在 Java 操做數堆棧中操做的,但對它們的表示卻徹底不一樣。(本文中如下部分將用通用術語堆棧代替操做數堆棧或局部變量表。)原始類型 int 和對象引用各佔堆棧的 32 位。(要表示一個 int 或一個對象引用,Java 虛擬機實現至少須要使用 32 位存儲。)Integer 對象的堆棧項並非對象自己,而是一個對象引用。spa
Java 中的全部對象都要經過對象引用訪問。對象引用是指向對象存儲所在堆中的某個區域的指針。當聲明一個原始類型時,就爲類型自己聲明瞭存儲。指針
引用類型和原始類型具備不一樣的特徵和用法,它們包括:大小和速度問題,這種類型以哪一種類型的數據結構存儲,當引用類型和原始類型用做某個類的實例數據時所指定的缺省值。對象引用實例變量的缺省值爲 null,而原始類型實例變量的缺省值與它們的類型有關。code
許多程序的代碼將同時包含原始類型以及它們的對象封裝。當檢查它們是否相等時,同時使用這兩種類型並瞭解它們如何正確相互做用和共存將成爲問題。程序員必須瞭解這兩種類型是如何工做和相互做用的,以免代碼出錯。orm
例如,不能對原始類型調用方法,但能夠對對象調用方法:對象
int j = 5; j.hashCode(); // 錯誤 //。.. Integer i = new Integer(5); i.hashCode(); // 正確
使用原始類型無須調用 new,也無須建立對象。這節省了時間和空間。混合使用原始類型和對象也可能致使與賦值有關的意外結果。看起來沒有錯誤的代碼可能沒法完成您但願作的工做。例如:ci
import java.awt.Point; class Assign { public static void main(String args[]) { int a = 1; int b = 2; Point x = new Point(0,0); Point y = new Point(1,1); //1 System.out.println(「a is 」 + a); System.out.println(「b is 」 + b); System.out.println(「x is 」 + x); System.out.println(「y is 」 + y); System.out.println(「Performing assignment and 」 + 「setLocation.。.」); a = b; a++; x = y; //2 x.setLocation(5,5); //3 System.out.println(「a is 」+a); System.out.println(「b is 」+b); System.out.println(「x is 」+x); System.out.println(「y is 」+y); } }
這段代碼生成如下輸出:
a is 1 b is 2 x is java.awt.Point[x=0,y=0] y is java.awt.Point[x=1,y=1] Performing assignment and setLocation.。. a is 3 b is 2 x is java.awt.Point[x=5,y=5] y is java.awt.Point[x=5,y=5]
修改整數 a 和 b 的結果沒什麼意外的地方。b 的值被賦予整型變量 a,結果 a 的值增長了 1。這一輸出反映了咱們但願發生的狀況。可是,使人感到意外的,是在賦值並調用 setLocation以後 x 和 y 對象的輸出。咱們在完成 x = y 賦值以後特地對 x 調用了 setLocation,x 和 y 的值怎麼會相同呢?咱們畢竟將 y 賦予 x,而後更改了 x,這與咱們對整數 a 和 b 進行的操做沒什麼不一樣。
這種混淆是由原始類型和對象的使用形成的。賦值對這兩種類型所起的做用沒什麼不一樣。但它可能看起來全部不一樣。賦值使等號 (=) 左邊的值等於右邊的值。這一點對於原始類型(如前面的 int a 和 b)是顯而易見的。對於非原始類型(如 Point 對象),賦值修改的是對象引用,而不是對象自己。所以,在語句
x = y;
以後,x 等於 y。換句話說,由於 x 和 y 是對象引用,它們如今引用同一個對象。所以,對 x 所做的任何更改也會更改 y。下面是 //1 處的代碼執行之後的狀況:
執行 //2 處的賦值之後狀況以下:
當在 //3 處調用 setLocation 時,這一方法是對 x 引用的對象執行的。由於 x 引用的 Point 對象也正是 y 所引用的對象,因此咱們如今獲得如下結果:
由於 x 和 y 引用同一個對象,因此對 x 執行的全部方法與對 y 執行的方法都做用於同一個對象。
區分引用類型和原始類型並理解引用的語義是很重要的。若作不到這一點,則會使編寫的代碼沒法完成預約工做。
但願經過以上內容的介紹,可以給你帶來幫助。
另外,引用類型的一些優點:
對象能夠被序列化,原始類型不行。 對象提供的方法能夠靈活轉換,能夠擴展,原始類型不行 在集合類中只能使用對象,不能使用原始類型 原始類型沒有null的概念,對象有,某些狀況下須要辨別某個參數是否被初始化了,若是使用原始類型,那麼0的值不知道是初始值仍是沒有初始化系統自動給的。 引用類型能夠封裝