String類使用陷阱深度解析

String

在這裏插入圖片描述

doc

  • String類表示字符串。Java程序中的所有字符串文本(如“abc”)都作爲此類的實例實現。
  • 字符串是常量;它們的值在創建後不能更改。字符串緩衝區支持可變字符串。因爲字符串對象是不可變的,所以可以共享它們。例如:
String str = "abc";

相當於:
char data[] = {'a', 'b', 'c'};
String str = new String(data);

以下是有關如何使用字符串的更多示例:

System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);

  • 類字符串包括用於檢查序列的單個字符、比較字符串、搜索字符串、提取子字符串以及創建字符串副本的方法,其中所有字符都轉換爲大寫或小寫。大小寫映射基於Character類指定的Unicode標準版本
  • Java語言提供了對字符串連接運算符(+)以及將其他對象轉換爲字符串的特殊支持。字符串連接是通過StringBuilder(或StringBuffer)類及其append方法實現的。字符串轉換是通過toString方法實現的,由Object定義並由Java中的所有類繼承。
  • 除非另有說明,否則向此類中的構造函數或方法傳遞null參數將導致引發NullPointerException。
/*
返回字符串對象的規範表示形式。
字符串池最初是空的,由類String單獨維護。
當調用intern方法時,如果池中已經包含一個與equals(object)方法確定的字符串對象相等的字符串,則返回池中的字符串。否則,此字符串對象將添加到池中,並返回對此字符串對象的引用。
因此,對於任何兩個字符串s和t,s.intern()==t.intern()是真時則必須先滿足s.equals(t)必須爲真。
*/
    public native String intern();
/*重新Objectequals*/
  public boolean equals(Object anObject) {
        if (this == anObject) {
        	//引用一致
            return true;
        }
        //判斷參數是否是String實例及其子類
        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;
    }

相等性的比較(==)

  • 對於原生數據類型來說,比較的是左右兩邊的值是否相等。

  • 對於引用類型來說,比較左右兩邊的引用是否指向同一個對象,或者說左右兩 邊的引用地址是否相同。

  • 對於 String 類的 equals() 方法來說,它是判斷當前字符串與傳進來的字符串的內容
    是否一致。

  • 對於 String 對象的相等性判斷來說,請使用 equals()方法,而不要使用==。

  • String 是常量,其對象一旦創建完畢就無法改變。當使用+拼接字符串時,會生成新
    的 String 對象,而不是向原有的 String 對象追加內容。

public class StringTest2
{
	public static void main(String[] args)
	{
		String s1 = "hello";
		String s2 = " world";
		String s3 = s1 + s2;

		System.out.println(s3);
	}
}

陷阱解析

public class ObjectTest2
{
	public static void main(String[] args)
	{
		Object object = new Object();
		Object object2 = new Object();

		System.out.println(object == object2);//false

		System.out.println("----------------");


		String str = new String("aaa");
		String str2 = new String("aaa");

		System.out.println(str == str2);//false

		System.out.println("----------------");

		String str3 = "bbb";
		String str4 = "bbb";

		System.out.println(str3 == str4);//true
		
		System.out.println("----------------");

		String str5 = new String("ccc");//指向堆引用
		String str6 = "ccc";//指向字符串池

		System.out.println(str5 == str6);//false

		System.out.println("----------------");

		String s = "hello";
		String s1 = "hel";
		String s2 = "lo";

		System.out.println(s == s1 + s2);//兩個引用相加 false

		System.out.println("----------------");

		System.out.println(s == "hel" + "lo");//兩個常量相加 true


	}
}

String Pool(棧中字符串池)

String s = “aaa”;(採用字面值方式賦值)

  1. 查找 String Pool 中是否存在“aaa”這個對象,如果不存在,則在 String Pool 中創建
    一個“aaa”對象,然後將 String Pool 中的這個“aaa”對象的地址返回來,賦給引
    用變量 s,這樣 s 會指向 String Pool 中的這個“aaa”字符串對象(此時創建0個對象)
  2. 如果存在,則不創建任何對象,直接將 String Pool 中的這個“aaa”對象地址返回來,
    賦給 s 引用。(此時創建一個對象)

String s = new String(“aaa”);創建幾個對象?

  1. 首先在 String Pool 中查找有沒有“aaa”這個字符串對象,如果有,則不在 String Pool
    中再去創建“aaa”這個對象了,直接在堆中(heap)中創建一個“aaa”字符串對
    象,然後將堆中的這個“aaa”對象的地址返回來,賦給 s 引用,導致 s 指向了堆中
    創建的這個“aaa”字符串對象。(此時創建了一個對象)
  2. 如果沒有,則首先在 String Pool 中創建一個“aaa“對象,然後再在堆中(heap)創
    建一個”aaa“對象,然後將堆中的這個”aaa“對象的地址返回來,賦給 s 引用,
    導致 s 指向了堆中所創建的這個”aaa“對象。(此時創建兩個對象)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章