### 1.什么是Java中的字符串
在 Java 中,字符串被作為 String 類型的對象處理。 String 類位于 java.lang 包中。默認情況下,該包被自動導入所有的程序。
創建 String 對象的方法:
~~~
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args){
// 創建一個字符串對象
String str = "xiaosi";
// 創建一個空字符串對象
String str2 = new String();
// 創建一個字符串對象
String str3 = new String("I am from China");
System.out.println("str->"+str);
System.out.println("str2->"+str2);
System.out.println("str3->"+str3);
}
}
~~~
### 2.Java字符串的不變性
String 對象創建后則不能被修改,是不可變的,所謂的修改其實是創建了新的對象,所指向的內存空間不同。如下所示:
~~~
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args){
String str1 = "xiaosi";
String str2 = "xiaosi";
String str3 = new String("I am from China");
String str4 = new String("I am from China");
// str1 str2 是字符串常量 Java編譯程序只創建一個 str1 str2 指向同一個對象
System.out.println("str1 == str2 "+(str1 == str2)); // true
// str1 str2是不同的對象
System.out.println("str1 == str3 "+(str1 == str3)); // false
// str3 str4是不同的對象
System.out.println("str3 == str4 "+(str3 == str4)); // false
str1 = "歡迎你 " + str1;
System.out.println("str1->"+str1); // 歡迎你 xiaosi
}
}
~~~
對于str1字符串看似修改了其值:(xiaosi ?-> ? 歡迎你 xiaosi)
~~~
str1 = "歡迎你 " + str1;
~~~
但其實不是表面那樣,str1實際上不在指向值為xiaosi的對象,而是指向了值為“歡迎你 xiaosi”對象上(新創建了一個對象)。
這樣做是否會降低運行效率呢?看起來好像修改一個代碼單元要比創建一個新字符串更加簡介。答案是:也對,也不對。通過拼接"歡迎你"和"xiaosi"來創建一個新字符串的效率確實不高。但是,不可變字符卻有一個有點:編譯器可以讓字符串達到共享。
為了弄清楚具體的工作方式,可以想象將各種字符串放入公共的字符串存儲池中,字符串變量指向字符串存儲池中相應位置。如果復制一個字符串變量,原始字符串與復制的字符串變量共享相同的字符。
Java設計者認為共享帶來的高效率遠遠勝于提取,拼接字符串所帶來的低效率。查看一下程序你就會發現:很少需要修改字符串,而是往往需要對字符串進行比較。
當str1重新指向一個新生成的對象時,你會不會想:這樣做會不會產生內存泄露呢?畢竟,原始字符串放置在堆中。對于這樣的情況,Java設計者已經想到,Java將會自動進行垃圾回收,如果一塊內存不在使用了,系統將會將其回收。
### 3.Java中字符串常用方法
String 類提供了許多用來處理字符串的方法,例如,獲取字符串長度、對字符串進行截取、將字符串轉換為大寫或小寫、字符串分割等,下面我們就來領略它的強大之處吧。

案例:
~~~
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args) {
// Java文件名
String fileName = "HelloWorld.jav";
// 郵箱
String email = "laurenyang@imooc.com";
// 判斷.java文件名是否正確:合法的文件名應該以.java結尾
/*
參考步驟:
1、獲取文件名中最后一次出現"."號的位置
2、根據"."號的位置,獲取文件的后綴
3、判斷"."號位置及文件后綴名
*/
//獲取文件名中最后一次出現"."號的位置
int index = fileName.lastIndexOf('.');
// 獲取文件的后綴
String prefix = fileName.substring(index+1);
// 判斷必須包含"."號,且不能出現在首位,同時后綴名為"java"
if (index != -1 && index != 0 && prefix.equals("java")) {
System.out.println("Java文件名正確");
} else {
System.out.println("Java文件名無效");
}
// 判斷郵箱格式是否正確:合法的郵箱名中至少要包含"@", 并且"@"是在"."之前
/*
參考步驟:
1、獲取文件名中"@"符號的位置
2、獲取郵箱中"."號的位置
3、判斷必須包含"@"符號,且"@"必須在"."之前
*/
// 獲取郵箱中"@"符號的位置
int index2 = email.indexOf('@');
// 獲取郵箱中"."號的位置
int index3 = email.indexOf('.');
// 判斷必須包含"@"符號,且"@"必須在"."之前
if (index2 != -1 && index3 > index2) {
System.out.println("郵箱格式正確");
} else {
System.out.println("郵箱格式無效");
}
}
}
~~~
~~~
public class HelloWorld {
public static void main(String[] args) {
// 定義一個字符串
String s = "aljlkdsflkjsadjfklhasdkjlflkajdflwoiudsafhaasdasd";
// 出現次數
int num = 0;
// 循環遍歷每個字符,判斷是否是字符 a ,如果是,累加次數
for (int i = 0;i < s.length();++i)
{
// 獲取每個字符,判斷是否是字符a
if (s.charAt(i) == 'a') {
// 累加統計次數
num++;
}
}
System.out.println("字符a出現的次數:" + num);
}
}
~~~

### 4.== 和 equals區別
==: 判斷兩個字符串在內存中首地址是否相同,即判斷是否是同一個字符串對象
equals(): 比較存儲在兩個字符串對象中的內容是否一致
### 5.StringBuilder 類
在Java中,除了可以使用 String 類來存儲字符串,還可以使用 StringBuilder 類或 StringBuffer 類存儲字符串,那么它們之間有什么區別呢?
~~~
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args) {
String str = "xiaosi";
System.out.println(str + " hello");
System.out.println(str);
}
}
~~~
運行結果:
~~~
xiaosi hello
xiaosi
~~~
從運行結果中我們可以看到,程序運行時會額外創建一個對象,保存 "xiaosi hello"。當頻繁操作字符串時,就會額外產生很多臨時變量。使用 StringBuilder 或 StringBuffer 就可以避免這個問題。至于 StringBuilder 和StringBuffer ,它們基本相似,不同之處,StringBuffer 是線程安全的,而 StringBuilder 則沒有實現線程安全功能,所以性能略高。因此一般情況下,如果需要創建一個內容可變的字符串對象,應優先考慮使用 StringBuilder 類。
那么如何定義 StringBuilder 類的對象呢? 我們來看下面的代碼:
~~~
package com.qunar.test;
public class HelloWorld {
public static void main(String[] args) {
StringBuilder str = new StringBuilder("xiaosi");
System.out.println(str);
}
}
~~~
StringBuilder 類提供了很多方法來操作字符串:

例如:在下面的示例代碼中,創建了 StringBuilder 對象,用來存儲字符串,并對其做了追加和插入操作。這些操作修改了 str 對象的值,而沒有創建新的對象,這就是 StringBuilder 和 String 最大的區別。
~~~
public class HelloWorld {
public static void main(String[] args) {
// 創建一個空的StringBuilder對象
StringBuilder str = new StringBuilder();
// 追加字符串
str.append("jaewkjldfxmopzdm");
// 從后往前每隔三位插入逗號
for (int i = str.length()-3;i > 0;i = i - 3){
str.insert(i,',');
}
// 將StringBuilder對象轉換為String對象并輸出
System.out.print(str.toString());
}
}
~~~
- 前言
- [Hibernate開發之路](1)Hibernate配置
- [Hibernate開發之路](2)Hibernate問題
- [Hibernate開發之路](3)基礎配置
- [Hibernate開發之路](4)ID生成策略
- [Hibernate開發之路](5)聯合主鍵
- [設計模式實踐之路](1)單例模式
- [Java]UDP通信的簡單例子
- [Java]套接字地址InetAddress講解
- [Java開發之路](1)final關鍵字
- [Java開發之路](2)Java字符串
- [Java開發之路](3)Java常用類
- [Java開發之路](4)String、StringBuffer與StringBuilder詳解
- [Java開發之路](5)異常詳解
- [Java開發之路](6)File類的使用
- [Java開發之路](7)RandomAccessFile類詳解
- [Java開發之路](8)輸入流和輸出流
- [Java開發之路](9)對象序列化與反序列化
- [Java開發之路](10)DOM解析XML文檔
- [Java開發之路](11)SAX解析XML文檔
- [Java開發之路](12)JDOM和DOM4J解析XML文檔
- [Java開發之路](14)反射機制
- [Java開發之路](15)注解
- [Java開發之路](16)學習log4j日志
- [Java開發之路](18)關于Class.getResource和ClassLoader.getResource的路徑問題
- [Java開發之路](19)Long緩存問題
- [Java開發之路](20)try-with-resource 異常聲明
- [Java開發之路](21)Comparator與Comparable
- [Java]Java工程師成神之路
- [細說Java](1)圖說字符串的不變性
- [細說Java](2)Java中字符串為什么是不可變的
- [細說Java](3)創建字符串是使用&quot; &quot;還是構造函數?