String經典問題

String經典問題(==和equals區別,new String爲什麼創建了兩個對象)
2008年11月12日 09:58

// ==與equals的區別:
// ==:
// 1、比較的是操作符兩端的操作數是否是同一個對象
// 2、兩邊的操作數必須是同一類型的(可以是父子類之間)才能編譯通過。
// 3、比較的是地址,如果是具體的阿拉伯數字的比較,值相等則爲TRUE,如:
// int a=10 與 long b=10L 與 double c=10.0都是相同的(爲true),因爲他們都指向地址爲10的堆
// equals:
// 1、比較的是兩個對象的內容是否一樣

/*
* String s="abce"是一種非常特殊的形式,和new 有本質的區別.
*
* 它是java中唯一不需要new 就可以產生對象的途徑.
*
* 以 String s="abce";形式賦值在java中叫直接量,它是在常量池中而不是象new 一樣放在壓縮堆中.
* 這種形式的字符串,在JVM內部發生字符串拘留,即當聲明這樣的一個字符串後,JVM會在常量池中先查找有有沒有一個值爲"abcd"的對象,如果有,就會把它賦給當前引用.即原來那個引用和現在這個引用指點向了同一對象,如果沒有,則在常量池中新創建一個"abcd",下一次如果有String
* s1 = "abcd";又會將s1指向"abcd"這個對象,即以這形式聲明的字符串,只要值相等,任何多個引用都指向同一對象.
*
* 而String s = new String("abcd");和其它任何對象一樣.每調用一次就產生一個對象.只到它們調用
*/

public class Test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 爲一個引用
String b = new String("ab"); // b爲另一個引用,對象的內容一樣
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 從常量池中查找
if (aa == bb) // true
   System.out.println("aa==bb");
if (a == b) // false
   System.out.println("a==b");
if (a.equals(b)) // true
   System.out.println("aEQb");
if (42 == 42.0) { // true
   System.out.println("true");
}
}
}

/*
* 也可以這麼理解:
* String str = "hello"; 先在內存中找是不是有"hello"
* 這個對象,如果有,就讓str指向那個"hello".如果內存裏沒有"hello",就創建一個新的對象保存"hello". String str=new
* String ("hello") 就是不管內存裏是不是已經有"hello"這個對象,都新建一個對象保存"hello"
*/
/*
* String a = new String("ab");是在堆裏面建立的對象 String,a和"ab"
* aa="ab";是查找棧裏有沒有"ab",如果有就用aa引用它,如果沒有就把“ab”存進棧
*/

 

附加:

Java中沒有指針,但存在“引用”的概念;下面從內存分配的角度,分析一下java中的變量。以下的程序都比較簡單,各位慢慢看,
【程序一】
class main
{
public static void main(String[] args)
{
    String s1="Hello world1";
    String s2=s1;
    System.out.println("s1=" + s1);
    System.out.println("s2=" + s2);
    s2="abcdef";
    System.out.println("s1=" + s1);
    System.out.println("s2=" + s2);
}
}

程序輸出結果如下:
---------- 運行 ----------
s1=Hello world1
s2=Hello world1
s1=Hello world1
s2=abcdef
Normal Termination
輸出完成(耗時 1 秒)。

程序分析:
String s2=s1; 從java的角度理解,應該是s2和s1共同指向了"Hello world1" 字符串所佔用的內存空間;
下面的賦值s2="abcdef";又將變量s2執行了"abcdef"字符串所佔用的內存空間,此時s1,s2分別指向了不同的內存空間。

【程序二】
class main
{
public static void main(String[] args)
{
    String s="Hello world1";
    System.out.println("s=" + s);
    s="Hello world2";
    System.out.println("s=" + s);
    s="Hello world3";
    System.out.println("s=" + s);
}
}

程序輸出結果如下:
---------- 運行 ----------
s=Hello world1
s=Hello world2
s=Hello world3
Normal Termination
輸出完成(耗時 0 秒)。

程序分析:
這例程序和上例不同之處是隻使用了一個變量s。
String s="Hello world1"; 定義了一個字符串的引用s,並將其指向"Hello world1"字符串所佔用的內存空間;
s="Hello world2"; 使s指向了"Hello world2" 字符串所佔用的內存空間;
這是"Hello world1"所佔用的空間沒有變量使用,會被jvm的垃圾回收機制回收。
s="Hello world3"; 也是同樣的道理。

總結:
定義java變量的時候,實際上只是產生了一個指向該類型的引用(它也佔用內存空間),對這個“引用”進行賦值,是將其指向某個內存空間;多次對“引用”進行賦值,jvm會產生多個內存空間,同時回收以前不用的內存空間。
有鑑於此,可知,java在使用內存方面是毫不吝惜的,變量定義與賦值時,會盡可能多的產生內存空間,不用的內存空間交給jvm的垃圾回收機制。

【轉】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章