Java中String直接賦字符串和new String的區別 如String str=new String("a")和String str = "a"有什麼區別?

百度的面試官問html

String A="ABC";面試

String B=new String("ABC");post

這兩個值,A,B 是否相等,若是都往HashSet裏面放,能放下嗎?this

答:(a)A==B 的判斷爲false;url

         (b)A.equals(B)爲true ;由於值相等,因此都往HashSet裏面放不下,只能放一個 spa

 問題:==與equals()的區別:

  1. ==:比較引用類型比較的是地址值是否相同
  2. equals:比較引用類型默認也是比較地址值是否相同,注意:String類重寫了equals()方法,比較的是內容是否相同。

String A = "ABC";內存會去查找永久代(常量池) ,若是沒有的話,在永久代中中開闢一起內存空間,把地址付給棧指針,若是已經有了"ABC"的內存,直接把地址賦給棧指針;指針

所以 code

String str1="aa";orm

Srting str2="aa";htm

String Str3="aa";

....

這樣下去,str1==Str2==str3;會一直相等下去,(a) ==的判斷, (b) equals()的判斷;都相等,由於他們的地址都相等,所以只在常量池中有一分內存空間,地址所有相同; 

  而String str = new String("a");是根據"a"這個String對象再次構造一個String對象;在堆中重新new一起內存,把指針賦給棧,

將新構造出來的String對象的引用賦給str。 所以 只要是new String(),則,棧中的地址都是指向最新的new出來的堆中的地址,

(a)「」==「」 是判斷地址的,固然不相同;

(b)至於equals,String類型重寫了 equals()方法,判斷值是否相等,明顯相等,所以 equals 是相等的;

這是String 重寫的equals:

 * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

 

public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = "hello";
        System.out.println(s1 == s2);// false
        System.out.println(s1.equals(s2));// true
    }
}
**運行結果:**

> false 
> true

代碼詳解

  1. 首先,經過main()方法進棧。
  2. 而後再棧中定義一個對象s1,去堆中開闢一個內存空間,將內存空間的引用賦值給s1,「hello」是常量,而後去字符串常量池 查看是否有hello字符串對象,沒有的話分配一個空間存放hello,而且將其空間地址存入堆中new出來的空間中。
  3. 在棧中定義一個對象s2,而後去字符串常量池中查看是否有」hello」字符串對象,有,直接把」hello」的地址賦值給s2.
  4. 即s1中存的是堆中分配的空間,堆中分配的空間中存的是字符串常量池中分配空間存放」hello」的空間的地址值。而s2中之間存的是字符串常量池中分配空間存放」hello」的空間的地址值。
  5. 因爲s1與s2中存放的地址不一樣,因此輸出false。由於,類String重寫了equals()方法,它比較的是引用類型的 的值是否相等,因此輸出true。即結果爲false、true。

Demo1

public class StringDemo1 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1 == s2);// false
        System.out.println(s1.equals(s2));// true

        String s3 = new String("hello");
        String s4 = "hello";
        System.out.println(s3 == s4);// false
        System.out.println(s3.equals(s4));// true

        String s5 = "hello";
        String s6 = "hello";
        System.out.println(s5 == s6);// true
        System.out.println(s5.equals(s6));// true
    }
}

 

Demo1詳解

s1~s6用equals()的比較不解釋,都是比較的值,均爲true。如下講解==

  1. s一、s2:兩者均爲new出來的,各自在堆中分配有空間,並各自將內存地址賦值給s一、s2。空間地址不一樣,==比較爲false。可是各自在堆中空間中保存的值均爲在字符串常量池中的同一個對象的地址。根據Demo處的圖即解釋不難理解。
  2. s三、s4同上Demo出解釋。
  3. s五、s6都是在常量池中取值,兩者都指向常量池中同一對象,其地址值相同,因此結果爲true。

Demo2

public class StringDemo4 {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";
        String s3 = "helloworld";
        System.out.println(s3 == s1 + s2);// false
        System.out.println(s3.equals((s1 + s2)));// true
        System.out.println(s3 == "hello" + "world");//false
        System.out.println(s3.equals("hello" + "world"));// true
    }
}

 

Demo2詳解

equals()比較方法不解釋,比較值,均相等,均爲true。

  1. s1與s2相加是先在字符串常量池中開一個空間,而後拼接,這個空間的地址就是s1與s2拼接後的地址。與s3的地址不一樣,因此輸出爲false。
  2. s3與」hello」+」world」做比較,」hello」+」world」先拼接成」helloworld」,而後再去字符串常量池中找是否有」helloworld」,有,因此和s3共用一個字符串對象,則爲true。

總結

    1. String s = new String(「hello」)會建立2(1)個對象,String s = 「hello」建立1(0)個對象。 
      注:當字符串常量池中有對象hello時括號內成立!
    2. 字符串若是是變量相加,先開空間,在拼接。
    3. 字符串若是是常量相加,是先加,而後在常量池找,若是有就直接返回,不然,就建立。

 

參考:String str=new String("a")和String str = "a"有什麼區別?

相關文章
相關標籤/搜索