java雖然說是「一切皆對象」,可是也會引出一系列的關於對象建立的問題。如 String str1 = new String("aaabb"); 和 String str2 = "aaabb"; 的區別,抑或是上述兩個語句建立了多少個對象,(str1==str2) ? 這些說法其實我在以前也是不太肯定,僅有一些模糊的認識,接下來就一塊兒學習一下。html
首先避開string不談,string這個比較特殊,咱們先引入一個普通的對象,如User;java
User user1;
user1 = new User("張三");
User user2 = new User("李四");
複製代碼
上面兩個對象的建立有什麼區別嗎?確定是有的,其中對於user1來講,第一步只是先建立了一個user1類型的引用,而第二步,纔是在jvm的堆中實例化了一個User對象,完成了整個對象的建立。bash
而若是user1類型的對象引用在第一步時指向哪裏呢,應該是指向了null,null做爲java的一種特殊類型,我以爲既不能叫一種變量,也不能叫作一個對象,由於實在是太特殊了,兩種類型的特性都和它不吻合。所以得出結論,User user1 = new User("張三"); 這個語句建立了兩個對象,一個是User類型的引用對象,在jvm的棧中,實例化的對象則在jvm的堆中。jvm
String相較於普通對象有些特殊,那咱們依舊把String拉出來,建立對象和引用,以下:學習
String str1;
str1 = new String("123");
String str2 = new String("123");
String str3 = "123";
複製代碼
咱們依舊是和上面的操做方式同樣,建立了str1和str2,所以兩者的區別仍是是單首創建對象引用和對象實例化。但String有另外的建立方式,就是str3,str3的建立方式是這樣的:先去jvm字符串常量池中尋找有沒有 "123"的字符串常亮,若是有的話,則直接進行引用的賦值;若是沒有,則在常量池中建立"123"字符串,再進行引用賦值。所以又引出了對於String對象的==和.equals的的對比使用。以下:spa
String str1 = "123";
String str2 = "123";
String str3 = new String("123");
String str4 = new String("123");
System.out.println("str1==str2:"+(str1==str2));
System.out.println("str3==str4:"+(str3==str4));
System.out.println("str1==str3:"+(str1==str3));
System.out.println("str1.euqals(str3):"+(str1.equals(str3)));
————————————————————————————————————————————————————————————————————
str1==str2:true
str3==str4:false
str1==str3:false
str1.euqals(str3):true
複製代碼
結果如上,也就是說,直接建立的相同內容的string,是在常量池中,所以引用對象指向的地址爲同一個;而使用new String進行實例化的String類型,每次都是在棧中新建一個對象。code
關於常量池,又是另一個知識了,在java中,不少包裝類型都有本身的常量池,甚至有已經初始化的常量。包裝類的大部分都實現了常量池技術,這些類是Byte,Short,Integer,Long,Character,Boolean,另外兩種浮點數類型的包裝類則沒有實現。另外Byte,Short,Integer,Long,Character這5種整型的包裝類也只是在對應值小於等於127時纔可以使用對象池,也即對象不負責建立和管理大於127的這些類的對象。htm
所以在使用Integer類型時,即便使用了==這個操做符來比較大小,在-128-127之間都仍是有效的,但若是不在這個範圍內使用,便會出問題,所以對於對象的比較來講,仍是須要用專有的比較大小的方法,不然就是一個bug。對象
這篇文章探索了java中的對象與引用及部分常量池的使用及誤區,對於String類型來講,還能夠選擇將這個String對象強行加入至常量池中,具體可見intern方法 www.cnblogs.com/guozhenqian… 。blog
第一次在掘金上發表文章,不曉得效果怎麼樣。