1、什么是 Java 中的字符串
在程序開發中字符串無處不在,如用戶登陸時輸入的用戶名、密碼等使用的就是字符串。其實,在前面的章節中我們就已經使用了字符串,例如我們在控制臺中輸出的 "Hello World" 、 "imooc" 、"愛慕課"等。
在 Java 中,字符串被作為 String 類型的對象處理。 String 類位于 java.lang 包中。默認情況下,該包被自動導入所有的程序。
創建 String 對象的方法:
String s1="imooc"; //創建一個字符串對象imooc,名為s1
String s2=new String();//創建一個空字符串對象,名為2
String s3=new String("imooc");//創建一個字符串對象imooc,名為s3
2、Java 中字符串的不變性
String 對象創建后則不能被修改,是不可變的,所謂的修改其實是創建了新的對象,所指向的內存空間不同。如下所示:
String s1="愛慕課";
String s2="愛慕課";
String s3=new String("愛慕課");
String s4=new String("愛慕課");
//多次出現的字符常量,Java編譯程序只創建一個,所以返回true
System.out.println(s1==s2);
//s1和s3是不同的對象,所以返回false
System.out.println(s1==s3);
//s3和s4是不同的對象,所以返回false
System.out.println(s3==s4);
s1="歡迎來到:"+s1;
//字符串s1被修改,指向新的內存空間
System.out.println(s1);
結果
true
false
false
歡迎來到:愛慕課
結合上面的代碼,關于字符串小伙伴們必須需要了解滴:
1、 通過 String s1="愛慕課"; 聲明了一個字符串對象, s1 存放了到字符串對象的引用,在內存中的存放引用關系如下圖所示:
s1------->(愛慕課)堆內存
然后通過 s1="歡迎來到:"+s1; 改變了字符串 s1 ,其實質是創建了新的字符串對象,變量 s1 指向了新創建的字符串對象,如下圖所示:
s1-------->(歡迎來到:愛慕課)堆內存(愛慕課)
2、 一旦一個字符串在內存中創建,則這個字符串將不可改變。如果需要一個可以改變的字符串,我們可以使用StringBuffer或者StringBuilder(后面章節中會講到)。
3、 每次 new 一個字符串就是產生一個新的對象,即便兩個字符串的內容相同,使用 ”==” 比較時也為 ”false” ,如果只需比較內容是否相同,應使用 ”equals()” 方法(前面條件運算符章節講過哦~~)
public class HelloWorld {
public static void main(String[] args) {
String s1 = "imooc";
String s2 = "imooc";
//定義字符串s3,保存“I love”和s1拼接后的內容
String s3 = "I love " + s1;
// 比較字符串s1和s2
// imooc為常量字符串,多次出現時會被編譯器優化,只創建一個對象
System.out.println("s1和s2內存地址相同嗎?" + (s1 == s2));
//比較字符串s1和s3
System.out.println("s1和s3內存地址相同嗎?" + (s1 == s3) );
String s4 = "I love " + s1;
//比較字符串s4和s3
// s1是變量,s4在運行時才知道具體值,所以s3和s4是不同的對象
System.out.println("s3和s4內存地址相同嗎?" + (s4 == s3));
}
}
3、Java 中 String 類的常用方法 Ⅰ
String 類提供了許多用來處理字符串的方法,例如,獲取字符串長度、對字符串進行截取、將字符串轉換為大寫或小寫、字符串分割等,下面我們就來領略它的強大之處吧。
String 類的常用方法:
方法 | 說明 |
---|---|
int length() | 返回當前字符串長度 |
int indexOf(int ch) | 查找ch字符在該字符串中第一次出現的位置 |
int indexOf(String str) | 查找str字符在該字符串中第一次出現的位置 |
int lastIndexOf(int ch) | 查找ch字符在該字符串中最后一次出現的位置 |
int lastIndexOf(String str) | 查找str字符在該字符串中最后一次出現的位置 |
String substring(int beginIndex) | 獲取從beginIndex位置開始到結束的子字符串 |
String substring(int beginIndex,int endIndex) | 獲取從beginIndex位置開始到endIndex位置的子字符串 |
String trim() | 返回去除了前后空格的字符串 |
boolean equals(Object obj | 將該字符串與指定對象比較,返回true或false |
String toLowerCase() | 將字符串轉換為小寫 |
String toUpperCase() | 將字符串轉換為大寫 |
char charAt(int index) | 獲取字符串中指定位置的字符 |
String[] aplit(String regex,int limit) | 將字符串分割為子字符串,返回字符串數組 |
byte[] getBytes() | 將該字符串轉換為byte數組 |
結合代碼來熟悉一下方法的使用:
import java.util.Arrays;
public class en {
public static void main(String[] args) {
// TODO Auto-generated method stub
//定義一個字符串"學習 Java 編程"
String str="學習 Java 編程";
//打印出字符串長度
System.out.println("字符串長度:"+str.length());
//查找字符“編”的位置
char c='編';
System.out.println("字符'編'的位置:"+str.indexOf(c));
//查找子字符串'Java'的位置
System.out.println("字符'編'的位置:"+str.indexOf("Java"));
//查找子字符串"imooc"的位置,如果找不到返回-1
System.out.println("字符'編'的位置:"+str.indexOf("imooc"));
//按空格吧字符拆分成一個數組,并輸出數組元素
String[] arr=str.split("");
System.out.println("按空格拆分成數組:"+Arrays.toString(arr));
System.out.println();
//獲取索引位置[3,7)之間的子串
System.out.println("獲取位置[3,7)之間的子串:"+str.substring(3,7));
}
}
字符串長度:10
字符'編'的位置:8
字符'編'的位置:3
字符'編'的位置:-1
按空格拆分成數組:[學, 習, , J, a, v, a, , 編, 程]
獲取位置[3,7)之間的子串:Java
友情提示:
- 字符串 str 中字符的索引從0開始,范圍為 0 到 str.length()-1
- 使用 indexOf 進行字符或字符串查找時,如果匹配返回位置索引;如果沒有匹配結果,返回 -1
- 使用 substring(beginIndex , endIndex) 進行字符串截取時,包括 beginIndex 位置的字符,不包括 endIndex 位置的字符
針對如此繁雜的方法,推薦大家一個學習技巧:好記性不如爛筆頭!多看的同時一定要多敲哦~~
public class en {
public static void main(String[] args) {
// Java文件名
String fileName = "HelloWorld.java";
// 郵箱
String email = "laurenyang@imooc.com";
// 判斷.java文件名是否正確:合法的文件名應該以.java結尾
/*
參考步驟:
1、獲取文件名中最后一次出現"."號的位置
2、根據"."號的位置,獲取文件的后綴
3、判斷"."號位置及文件后綴名
*/
//獲取文件名中最后一次出現"."號的位置
int index =fileName.indexOf(".");
// 獲取文件的后綴
String prefix =fileName.substring(index+1,fileName.length());
// 判斷必須包含"."號,且不能出現在首位,同時后綴名為"java"
if ( 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("郵箱格式無效");
}
}
}
4、Java 中的 String 類常用方法 Ⅱ
我們繼續來看 String 類常用的方法,如下代碼所示:
public class en {
public static void main(String[] args) {
//定義一個字符串“學習 Java 編程”
String str ="學習 Java 編程";
//將字符串轉換為小寫
System.out.println("轉換為小寫:"+str.toLowerCase());
//獲取索引位置為1的字符
System.out.println("獲取索引為1位置的字符:"+str.charAt(1));
//將字符串轉換為byte[],并打印輸出
byte[] b=str.getBytes();
System.out.println("轉換為字節數組:");
for(int i=0;i<b.length ;i++){
System.out.print(b[i]+"");
}
System.out.println();
//和另外一個字符串“學習 Java 編程”進行性比較
String str2=new String("學習 Java 編程");
System.out.println("str和str2的內存地址相同?"+(str==str2));
System.out.println("str和str2的內容相同?"+str.equals(str2));
}
}
轉換為小寫:學習 java 編程
獲取索引為1位置的字符:習
轉換為字節數組:
-47-89-49-803274971189732-79-32-77-52
str和str2的內存地址相同?false
str和str2的內容相同?true
那么,“==” 和 equals() 有什么區別呢?
==: 判斷兩個字符串在內存中首地址是否相同,即判斷是否是同一個字符串對象
equals(): 比較存儲在兩個字符串對象中的內容是否一致
PS:字節是計算機存儲信息的基本單位,1 個字節等于 8 位, gbk 編碼中 1 個漢字字符存儲需要 2 個字節,1 個英文字符存儲需要 1 個字節。所以我們看到上面的程序運行結果中,每個漢字對應兩個字節值,如“學”對應 “-47 -89” ,而英文字母 “J” 對應 “74” 。同時,我們還發現漢字對應的字節值為負數,原因在于每個字節是 8 位,最大值不能超過 127,而漢字轉換為字節后超過 127,如果超過就會溢出,以負數的形式顯示。(關于編碼,我們在后面課程中會詳細介紹,小小期待哦~~)
第一種
public class en {
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);
}
}
第二種
public class en {
public static void main(String[] args) {
// 定義一個字符串
String s = "aljlkdsflkjsadjfklhasdkjlflkajdflwoiudsafhaasdasd";
// 出現次數
int num = 0;
// 循環遍歷每個字符,判斷是否是字符 a ,如果是,累加次數
for (byte bt:(s.getBytes()))
{
// 獲取每個字符,判斷是否是字符a
if (bt == 'a') {
// 累加統計次數
num++;
}
}
System.out.println("字符a出現的次數:" + num);
}
}
結果:字符a出現的次數:8
5、認識 Java 中的 StringBuilder 類
在Java中,除了可以使用 String 類來存儲字符串,還可以使用 StringBuilder 類或 StringBuffer 類存儲字符串,那么它們之間有什么區別呢?
String 類具有是不可變性。如
String str="hello";
System.out.println(str+"world");
System.out.println(str);
從運行結果中我們可以看到,程序運行時會額外創建一個對象,保存 "helloworld"。當頻繁操作字符串時,就會額外產生很多臨時變量。使用 StringBuilder 或 StringBuffer 就可以避免這個問題。至于 StringBuilder 和StringBuffer ,它們基本相似,不同之處,StringBuffer 是線程安全的,而 StringBuilder 則沒有實現線程安全功能,所以性能略高。因此一般情況下,如果需要創建一個內容可變的字符串對象,應優先考慮使用 StringBuilder 類。
那么如何定義 StringBuilder 類的對象呢? 我們來看下面的代碼:
StringBuilder str1=new StringBuilder();
StringBuilder str2=new StringBuilder("imooc");
System.out.println(str2);
6、Java 中的 StringBuilder 類的常用方法
StringBuilder 類提供了很多方法來操作字符串:
方法 | 說明 |
---|---|
StringBuilder append(參數) | 追加內容到當前StringBuilder對象的末尾 |
StringBuilder insert(位置,參數) | 將內容插入到StringBuilder對象的指定位置 |
String toString() | 將StringBuilder對象轉換為String對象 |
int length() | 獲取字符串的長度 |
例如:在下面的示例代碼中,創建了 StringBuilder 對象,用來存儲字符串,并對其做了追加和插入操作。這些操作修改了 str 對象的值,而沒有創建新的對象,這就是 StringBuilder 和 String 最大的區別。
public class en {
public static void main(String[] args) {
//創建StringBuilder對象,存儲字符串
StringBuilder str=new StringBuilder("hello");
str.append(" imooc");//在字符串后面追加字符串
str.append(520);//在字符串后面追加整數
System.out.println("字符串長度:"+str.length());//字符串長度
System.out.println("插入前:"+str);
str.insert(11, "!");//在指定位置插入內容
String str2=str.toString();//轉換為String對象
System.out.println("插入后:"+str2);
}
}
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());
}
}
結果:j,aew,kjl,dfx,mop,zdm
在需要頻繁對字符串進行修改操作時使用 StringBuilder 的效率比 String 要高