(四)面向對象
11、String類
(1)概述
? ? ? ? <1>String是一個類,引用數據類型,用來表示字符串;
? ? ? ? <2>String是Lang包下的類,使用不需要導包;
? ? ??? <3>字符串的值不能變,String對象是不可變的,一旦創建,他們的值就不能被修改。
? ? ? ?這里的意思是String對象所標識的棧空間中的引用地址值可以改
? ? ? ?但是堆空間中創建的對象的屬性值不可以改變,一旦創建就不能更改!
示例:
String s1 = new String("123"); s1 = new String("345"); //這樣修改是可以的,并沒有改動上一個對象中的屬性123,只是更改了s1的引用地址值 s1 = null; //這樣修改也可以,將引用地址值指向了null
???????String類型的這個特點,使得很多操作其實都是在創建新的對象,并不是在原對象上操作
(2)String類的常用構造方法:? ??
下面給出一些案例:
public class Test_Basic {public static void main(String[] args) {// public String() : 創建一個空白字符串對象,不含有任何內容String s1 = new String();System.out.println(s1);// public String(char[] chs) : 根據字符數組的內容,來創建字符串對象char[] chs = {'a','b','c'};String s2 = new String(chs);System.out.println(s2);// public String(String original) : 根據傳入的字符串內容,來創建字符串對象String s3 = new String("123");System.out.println(s3);String s4 = "hello";System.out.println(s4);}
}
接下來是內存結構的展示:
(3)常量池:
????????創建字符串對象,和其他普通對象一樣,會占用計算機的資源(時間和空間),作為最常用的數據類型,大量頻繁的創建字符串對象,會極大程度地影響程序的性能。
????????JVM為了提高性能和減少內存開銷,在實例化字符串常量的時候進行了一些優化
String常量池:
????????在Java中,String常量池是一塊特殊的內存區域,用于存儲字符串常量。String常量池的設計目的是為了節省內存和提高性能。
????????當我們創建字符串常量時,如果字符串常量池中已經存在相同內容的字符串,那么新創建的字符串常量會直接引用已存在的字符串對象,而不會創建新的對象。這樣可以避免重復創建相同內容的字符串,節省內存空間。
????????在JDK8及之后的版本中,字符串常量池的位置與其他對象的存儲位置,都位于堆內存中。這樣做的好處是,字符串常量池的大小可以根據需要進行調整,并且可以享受到垃圾回收器對堆內存的優化。
????????Java將字符串放入String常量池的方式:
1. 直接賦值:通過直接賦值方式創建的字符串常量會被放入常量池中。
????????例如: String str = "Hello";
2. 調用String類提供intern()方法:可以將字符串對象放入常量池中,并返回常量池中的引用。
????????例如: String str = new String("World").intern();
????????注意:通過new關鍵字創建的字符串對象不會放 入常量池中,而是在堆內存中創建一個新的對象。只有通過直接賦值或調用intern()方法才能將字符串放入常量池中。
案例:
public class Test062_String {public static void main(String[] args) {String s1 = "Hello"; // 字符串常量,放入常量池String s2 = "Hello"; // 直接引用常量池中的字符串對象System.out.println(s1 == s2); // true,引用相同// 直接new String對象,不會將'World'放入常量池String s3 = new String("World");// 調用intern()方法,將'World'放入常量池,并返回常量池中的引用String s4 = new java.lang.String("World").intern();String s5 = "World";System.out.println(s3 == s4); // false,引用不同System.out.println(s4 == s5); // true,引用相同}
}
public class Test062_String2 {public static void main(String[] args) {String s1 = "a";String s2 = "b";// 常量優化機制:"a" 和 "b"都是字面值常量,借助 + 連接,其結果 "ab" 也被當作常量String s3 = "a" + "b";String s4 = "ab";System.out.println(s3.equals(s4)); // trueSystem.out.println(s3 == s4); // trueSystem.out.println("-------------");String s5 = s1 + s2;System.out.println(s4.equals(s5)); // trueSystem.out.println(s4 == s5); // falseSystem.out.println("-------------");String s6 = (s1 + s2).intern();System.out.println(s4.equals(s6)); // trueSystem.out.println(s4 == s6); // true}
}
使用 + 拼接多個字符串常量,拼接的結果仍舊是字符串常量 ,變量不可以如果結果字符串常量在常量池中不存在,則Java會將其放入到字符串常量池中
(4)常用方法:
1.?
public int length()
用法:獲取字符串的長度(字符個數)
返回值:
int
類型,即字符串中字符的數量調用者:
String
對象本身(如"abc".length()
)是否改變原對象:不改變。僅查詢長度,不修改字符串內容
示例:
String s = "hello"; int len = s.length(); // len = 5('h','e','l','l','o'共5個字符)
2.?
public boolean equals(Object anObject)
用法:比較當前字符串與參數對象的內容是否完全相同(嚴格區分大小寫)
返回值:
boolean
類型。true
表示內容完全相同,false
表示不同調用者:
String
對象本身(如s1.equals(s2)
)是否改變原對象:不改變。僅做比較操作,不修改任何字符串
注意:
需與
==
區分:equals()
比較內容,==
比較對象地址若參數為
null
,返回false
示例:
String s1 = "abc"; String s2 = "ABC"; boolean b1 = s1.equals("abc"); // true(內容相同) boolean b2 = s1.equals(s2); // false(大小寫不同)
3.?
public char charAt(int index)
用法:獲取字符串中指定索引位置的字符(索引從 0 開始)
返回值:
char
類型,即索引位置對應的字符調用者:
String
對象本身(如s.charAt(2)
)是否改變原對象:不改變。僅查詢指定位置的字符
注意:若索引超出范圍(
index < 0
或index >= length()
),會拋出StringIndexOutOfBoundsException
示例:
String s = "hello"; char c = s.charAt(1); // c = 'e'(索引1對應的字符)
4.?
public char[] toCharArray()
用法:將字符串轉換為字符數組(每個元素對應字符串中的一個字符)
返回值:
char[]
類型,即包含字符串所有字符的數組調用者:
String
對象本身(如s.toCharArray()
)是否改變原對象:不改變。僅生成新的字符數組,原字符串不變
示例:
String s = "abc"; char[] arr = s.toCharArray(); // arr = {'a','b','c'}
5.?
public String[] split(String regex)
用法:根據傳入的正則表達式
regex
切割字符串,返回切割后的子字符串數組返回值:
String[]
類型,即切割后的子字符串集合調用者:
String
對象本身(如s.split(",")
)是否改變原對象:不改變。僅根據規則切割并生成新數組,原字符串不變
注意:
regex
是正則表達式(如"\\."
表示按點切割,需轉義)若切割后無內容,可能返回空數組或包含空字符串
示例:
String s = "a,b,c"; String[] parts = s.split(","); // parts = {"a","b","c"}
6.?
public String substring(int begin, int end)
用法:截取字符串中從
begin
索引(包含)到end
索引(不包含)的子字符串,即范圍[begin, end)
返回值:
String
類型,即截取得到的新字符串調用者:
String
對象本身(如s.substring(1,3)
)是否改變原對象:不改變。生成新的子字符串,原字符串不變
注意:若
begin
或end
超出范圍,會拋出StringIndexOutOfBoundsException
示例:
String s = "hello"; String sub = s.substring(1,4); // sub = "ell"(索引1到3的字符:'e','l','l')
7.?
public String substring(int begin)
用法:從
begin
索引(包含)開始截取字符串,直到字符串末尾,即范圍[begin, length())
返回值:
String
類型,即截取得到的新字符串調用者:
String
對象本身(如s.substring(2)
)是否改變原對象:不改變。生成新的子字符串,原字符串不變
示例:
String s = "hello"; String sub = s.substring(2); // sub = "llo"(從索引2到末尾的字符)
8.?
public String replace(CharSequence target, CharSequence replacement)
用法:將字符串中所有與
target
匹配的子序列,替換為replacement
返回值:
String
類型,即替換后的新字符串調用者:
String
對象本身(如s.replace("a","b")
)是否改變原對象:不改變。生成替換后的新字符串,原字符串不變
注意:替換所有匹配項(非首次匹配)