java string对象创建_String对象创建个数
s = new String("xyz");創建了幾個String Object?兩個對象,一個是“xyx”,一個是指向“xyx”的引用對象s。
String s="你好";int i=3; s=i+s; 這個表達式對嗎?在java中會提示數據類型不匹配。因為string是類!正確做法: s+="3" 或者 s+='3'或者 s+=(char)i;
我們要引入另外一種創建String對象的方式的討論——引號內包含文本。這種方式是String特有的,并且它與new的方式存在很大區別。
在JAVA虛擬機(JVM)中存在著一個字符串池,其中保存著很多String對象,并且可以被共享使用,因此它提高了效率。String a="abc";,這行代碼被執行的時候,JAVA虛擬機首先在字符串池中查找是否已經存在了值為"abc"的這么一個對象,判斷依據是String類equals(Object obj)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然后把它加入到字符串池中,再將它的引用返回。
字符串對象的創建:由于字符串對象的大量使用[它是一個對象,一般而言對象總是在heap分配內存],Java中為了節省內存空間和運行時間[如比較字符串時,==比equals()快],在編譯階段就把所有的字符串文字放到一個文字池中,而運行時文字池成為常量池的一部分。文字池的好處,就是該池中所有相同的字符串常量被合并,只占用一個空間。我們知道,對兩個引用變量,使用==判斷它們的值[引用]是否相等,即指向同一個對象:
現在看String s = new String("abc");語句,這里"abc"本身就是pool中的一個對象,而在運行時執行new String()時,將pool中的對象復制一份放到heap中,并且把heap中的這個對象的引用交給s持有。ok,這條語句就創建了2個String對象。
String s1 = new String("abc") ;String s2 = new String("abc") ;if( s1 == s2 ){ //不會執行的語句}
//創建了幾個String Object? [三個,pool中一個,heap中2個。]
只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入字符串池中。對于所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中。
1.==表示引用自同一對象,equals()表示值相等。
String str1 = "abc";引用的對象在棧(或者叫String池)中。
String str1 =new String ("abc"); 引用的對象在內存/堆中。
2.String str1 =??"string";在棧中
String str3 =??"str";在棧中
String str4 = "ing";在棧中
String str2 = str3+str4; 在堆中,因為+號的作用是返回另外一個新建的String對象,而不是在棧中找string這個值。如果是String str2 = "str"+"ing";那最后的結果就在棧中。str1==str2為true。
但是有一種情況需要引起我們的注意。請看下面的代碼:
public class StringStaticTest {
public static final String A = "ab"; // 常量A
public static final String B = "cd"; // 常量B
public static void main(String[] args) {
String s = A + B;??// 將兩個常量用+連接對s進行初始化
String t = "abcd";
if (s == t) {
System.out.println("s等于t,它們是同一個對象");
} else {
System.out.println("s不等于t,它們不是同一個對象");
}
}
}
這段代碼的運行結果如下:
s等于t,它們是同一個對象
原因是在上面的例子中,A和B都是常量,值是固定的,因此s的值也是固定的,它在類被編譯時就已經確定了。也就是說:String s=A+B;??等同于:String s="ab"+"cd";
我對上面的例子稍加改變看看會出現什么情況:
public class StringStaticTest {
public static final String A; // 常量A
public static final String B;????// 常量B
static {
A = "ab";
B = "cd";
}
public static void main(String[] args) {
// 將兩個常量用+連接對s進行初始化
String s = A + B;
String t = "abcd";
if (s == t) {
System.out.println("s等于t,它們是同一個對象");
} else {
System.out.println("s不等于t,它們不是同一個對象");
}
}
}
它的運行結果是這樣:
s不等于t,它們不是同一個對象
只是做了一點改動,結果就和剛剛的例子恰好相反。我們再來分析一下。A和B雖然被定義為常量(只能被賦值一次),但是它們都沒有馬上被賦值。在運算出s的值之前,他們何時被賦值,以及被賦予什么樣的值,都是個變數。因此A和B在被賦值之前,性質類似于一個變量。那么s就不能在編譯期被確定,而只能在運行時被創建了。
最后我們再來說說String對象在JAVA虛擬機(JVM)中的存儲,以及字符串池與堆(heap)和棧(stack)的關系。我們首先回顧一下堆和棧的區別:
棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據可以共享,速度僅次于寄存器(register),快于堆。
堆(heap):用于存儲對象。
我們查看String類的源碼就會發現,它有一個value屬性,保存著String對象的值,類型是char[],這也正說明了字符串就是字符的序列。當執行String a="abc";時,JAVA虛擬機會在棧中創建三個char型的值'a'、'b'和'c',然后在堆中創建一個String對象,它的值(value)是剛才在棧中創建的三個char型值組成的數組{'a','b','c'},最后這個新創建的String對象會被添加到字符串池中。
如果我們接著執行String b=new String("abc");代碼,由于"abc"已經被創建并保存于字符串池中,因此JAVA虛擬機只會在堆中新創建一個String對象,但是它的值(value)是共享前一行代碼執行時在棧中創建的三個char型值值'a'、'b'和'c'。
說到這里,我們對于篇首提出的String str=new String("abc")為什么是創建了兩個對象這個問題就已經相當明了了。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yakihappy/archive/2009/03/10/3977169.aspx
本文來源:CSDN博客
總結
以上是生活随笔為你收集整理的java string对象创建_String对象创建个数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vcenter用到java吗_Vijav
- 下一篇: java保存多张图片格式_从多个URL下