一鳞青、String簡介
1.1、String(字符串常量)概述
在API中是這樣描述:
String 類代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作為此類的實例實現(xiàn)攀圈。 字符串是常量搓彻;它們的值在創(chuàng)建之后不能更改。字符串緩沖區(qū)支持可變的字符串完域。因為 String 對象是不可變的软吐,所以可以共享。
java.lang.String:
1.2吟税、分析String源碼
1)String的成員變量
/** String的屬性值 */
private final char value[];
/** The offset is the first index of the storage that is used. */
/**數(shù)組被使用的開始位置**/
private final int offset;
/** The count is the number of characters in the String. */
/**String中元素的個數(shù)**/
private final int count;
/** Cache the hash code for the string */
/**String類型的hash值**/
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
從源碼看出String底層使用一個字符數(shù)組來維護的凹耙。
成員變量可以知道String類的值是final類型的姿现,不能被改變的,所以只要一個值改變就會生成一個新的String類型對象肖抱,存儲String數(shù)據(jù)也不一定從數(shù)組的第0個元素開始的备典,而是從offset所指的元素開始。
2)String的構(gòu)造方法
String()
初始化一個新創(chuàng)建的 String 對象意述,使其表示一個空字符序列提佣。
String(byte[] bytes)
通過使用平臺的默認字符集解碼指定的 byte 數(shù)組,構(gòu)造一個新的 String荤崇。
String(byte[] bytes, Charset charset)
通過使用指定的 charset 解碼指定的 byte 數(shù)組拌屏,構(gòu)造一個新的 String。
String(byte[] bytes, int offset, int length)
通過使用平臺的默認字符集解碼指定的 byte 子數(shù)組天试,構(gòu)造一個新的 String槐壳。
String(byte[] bytes, int offset, int length, Charset charset)
通過使用指定的 charset 解碼指定的 byte 子數(shù)組,構(gòu)造一個新的 String喜每。
String(byte[] bytes, int offset, int length, String charsetName)
通過使用指定的字符集解碼指定的 byte 子數(shù)組务唐,構(gòu)造一個新的 String。
String(byte[] bytes, String charsetName)
通過使用指定的 charset 解碼指定的 byte 數(shù)組带兜,構(gòu)造一個新的 String枫笛。
String(char[] value)
分配一個新的 String,使其表示字符數(shù)組參數(shù)中當(dāng)前包含的字符序列刚照。
String(char[] value, int offset, int count)
分配一個新的 String刑巧,它包含取自字符數(shù)組參數(shù)一個子數(shù)組的字符。
String(int[] codePoints, int offset, int count)
分配一個新的 String无畔,它包含 Unicode 代碼點數(shù)組參數(shù)一個子數(shù)組的字符啊楚。
String(String original)
初始化一個新創(chuàng)建的 String 對象,使其表示一個與參數(shù)相同的字符序列浑彰;換句話說恭理,新創(chuàng)建的字符串是該參數(shù)字符串的副本。
String(StringBuffer buffer)
分配一個新的字符串郭变,它包含字符串緩沖區(qū)參數(shù)中當(dāng)前包含的字符序列颜价。
String(StringBuilder builder)
分配一個新的字符串,它包含字符串生成器參數(shù)中當(dāng)前包含的字符序列诉濒。
二周伦、創(chuàng)建字符串對象兩種方式的區(qū)別
2.1、直接賦值方式創(chuàng)建對象
直接賦值方式創(chuàng)建對象是在方法區(qū)的常量池
String str="hello";//直接賦值的方式
2.2未荒、通過構(gòu)造方法創(chuàng)建字符串對象
通過構(gòu)造方法創(chuàng)建字符串對象是在堆內(nèi)存
String str=new String("hello");//實例化的方式
2.3专挪、兩種實例化方式的比較
1)編寫代碼比較
public class TestString {
public static void main(String[] args) {
String str1 = "Lance";
String str2 = new String("Lance");
String str3 = str2; //引用傳遞,str3直接指向st2的堆內(nèi)存地址
String str4 = "Lance";
/**
* ==:
* 基本數(shù)據(jù)類型:比較的是基本數(shù)據(jù)類型的值是否相同
* 引用數(shù)據(jù)類型:比較的是引用數(shù)據(jù)類型的地址值是否相同
* 所以在這里的話:String類對象==比較,比較的是地址狈蚤,而不是內(nèi)容
*/
System.out.println(str1==str2);//false
System.out.println(str1==str3);//false
System.out.println(str3==str2);//true
System.out.println(str1==str4);//true
}
}
2)內(nèi)存圖分析
可能這里還是不夠明顯困肩,構(gòu)造方法實例化方式的內(nèi)存圖:String str = new String("Hello");
首先:
當(dāng)我們再一次的new一個String對象時:
3)字符串常量池
在字符串中,如果采用直接賦值的方式(String str="Lance")進行對象的實例化脆侮,則會將匿名對象“Lance”放入對象池锌畸,每當(dāng)下一次對不同的對象進行直接賦值的時候會直接利用池中原有的匿名對象,
這樣靖避,所有直接賦值的String對象潭枣,如果利用相同的“Lance”,則String對象==返回true幻捏;
比如:對象手工入池
public class TestString {
public static void main(String args[]){
String str =new String("Lance").intern();//對匿名對象"hello"進行手工入池操作
String str1="Lance";
System.out.println(str==str1);//true
}
}
4)總結(jié):兩種實例化方式的區(qū)別
1)直接賦值(String str = "hello"):只開辟一塊堆內(nèi)存空間盆犁,并且會自動入池,不會產(chǎn)生垃圾篡九。
2)構(gòu)造方法(String str= new String("hello");):會開辟兩塊堆內(nèi)存空間谐岁,其中一塊堆內(nèi)存會變成垃圾被系統(tǒng)回收,而且不能夠自動入池榛臼,需要通過public String intern();方法進行手工入池伊佃。
在開發(fā)的過程中不會采用構(gòu)造方法進行字符串的實例化。
5)避免空指向
首先了解: == 和public boolean equals()比較字符串的區(qū)別
==在對字符串比較的時候沛善,對比的是內(nèi)存地址航揉,而equals比較的是字符串內(nèi)容,在開發(fā)的過程中金刁,equals()通過接受參數(shù)帅涂,可以避免空指向。
舉例:
String str = null;
if(str.equals("hello")){//此時會出現(xiàn)空指向異常
...
}
if("hello".equals(str)){//此時equals會處理null值尤蛮,可以避免空指向異常
...
}
6)String類對象一旦聲明則不可以改變媳友;而改變的只是地址,原來的字符串還是存在的产捞,并且產(chǎn)生垃圾
三醇锚、String常用的方法
3.1、String的判斷功能
1)常用方法
boolean equals(Object obj):比較字符串的內(nèi)容是否相同
boolean equalsIgnoreCase(String str): 比較字符串的內(nèi)容是否相同,忽略大小寫
boolean startsWith(String str): 判斷字符串對象是否以指定的str開頭
boolean endsWith(String str): 判斷字符串對象是否以指定的str結(jié)尾
2)代碼測試
public class TestString {
public static void main(String[] args) {
// 創(chuàng)建字符串對象
String s1 = "hello";
String s2 = "hello";
String s3 = "Hello";
// boolean equals(Object obj):比較字符串的內(nèi)容是否相同
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println("-----------");
// boolean equalsIgnoreCase(String str):比較字符串的內(nèi)容是否相同,忽略大小寫
System.out.println(s1.equalsIgnoreCase(s2));
System.out.println(s1.equalsIgnoreCase(s3));
System.out.println("-----------");
// boolean startsWith(String str):判斷字符串對象是否以指定的str開頭
System.out.println(s1.startsWith("he"));
System.out.println(s1.startsWith("ll"));
}
}
結(jié)果:
3.2轧葛、String類的獲取功能
1)常用方法
int length():獲取字符串的長度搂抒,其實也就是字符個數(shù)
char charAt(int index):獲取指定索引處的字符
int indexOf(String str):獲取str在字符串對象中第一次出現(xiàn)的索引
String substring(int start):從start開始截取字符串
String substring(int start,int end):從start開始艇搀,到end結(jié)束截取字符串尿扯。包括start,不包括end
2)代碼測試
public class TestString {
public static void main(String[] args) {
String str1 = "Lance";
String str2 = new String("Lance");
String str3 = "LANCE";
// boolean equals(Object obj):比較字符串的內(nèi)容是否相同
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
System.out.println("-----------------------");
// boolean equalsIgnoreCase(String str):比較字符串的內(nèi)容是否相同,忽略大小寫
System.out.println(str1.equalsIgnoreCase(str3));
System.out.println("-----------------------");
// boolean startsWith(String str):判斷字符串對象是否以指定的str開頭
// boolean endsWith(String str): 判斷字符串對象是否以指定的str結(jié)尾
System.out.println(str1.startsWith("La"));
System.out.println(str3.endsWith("CE"));
}
}
結(jié)果:
3.3焰雕、String的轉(zhuǎn)換功能
1)常用方法
char[] toCharArray():把字符串轉(zhuǎn)換為字符數(shù)組
String toLowerCase():把字符串轉(zhuǎn)換為小寫字符串
String toUpperCase():把字符串轉(zhuǎn)換為大寫字符串
2)核心代碼
public class TestString {
public static void main(String[] args) {
// 創(chuàng)建字符串對象
String s = "abcde";
// char[] toCharArray():把字符串轉(zhuǎn)換為字符數(shù)組
char[] chs = s.toCharArray();
for (int x = 0; x < chs.length; x++) {
System.out.println(chs[x]);
}
System.out.println("-----------");
// String toLowerCase():把字符串轉(zhuǎn)換為小寫字符串
System.out.println("HelloWorld".toLowerCase());
// String toUpperCase():把字符串轉(zhuǎn)換為大寫字符串
System.out.println("HelloWorld".toUpperCase());
}
}
結(jié)果:
注意:
字符串的遍歷有兩種方式:一是ength()加上charAt()衷笋。二是把字符串轉(zhuǎn)換為字符數(shù)組,然后遍歷數(shù)組矩屁。
3.4辟宗、其他常用方法
1)常用方法
去除字符串兩端空格:String trim()
按照指定符號分割字符串:String[] split(String str)
2)核心代碼
public class TestString {
public static void main(String[] args) {
// 創(chuàng)建字符串對象
String s1 = "helloworld";
String s2 = " helloworld ";
String s3 = " hello world ";
System.out.println("---" + s1 + "---");
System.out.println("---" + s1.trim() + "---");
System.out.println("---" + s2 + "---");
System.out.println("---" + s2.trim() + "---");
System.out.println("---" + s3 + "---");
System.out.println("---" + s3.trim() + "---");
System.out.println("-------------------");
// String[] split(String str)
// 創(chuàng)建字符串對象
String s4 = "aa,bb,cc";
String[] strArray = s4.split(",");
for (int x = 0; x < strArray.length; x++) {
System.out.println(strArray[x]);
}
}
}
結(jié)果: