字符串的學習,有的同學就看看API,記下方法,有的同學看看源代碼,還有的同學畫畫圖,自然學的深度是不一樣的。
/** * The {@code String} class represents character strings. All * string literals in Java programs, such as {@code "abc"}, are * implemented as instances of this class. * <p> * Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. For example: * <blockquote><pre> * String str="abc"; * </pre></blockquote><p> * is equivalent to: * <blockquote><pre> * char data[]={'a', 'b', 'c'}; * String str=new String(data); * </pre></blockquote><p> * Here are some more examples of how strings can be used: * <blockquote><pre> * System.out.println("abc"); * String cde="cde"; * System.out.println("abc" + cde); * String c="abc".substring(2,3); * String d=cde.substring(1, 2); * </pre></blockquote> * <p> * The class {@code String} includes methods for examining * individual characters of the sequence, for comparing strings, for * searching strings, for extracting substrings, and for creating a * copy of a string with all characters translated to uppercase or to * lowercase. Case mapping is based on the Unicode Standard version * specified by the {@link java.lang.Character Character} class. * <p> * The Java language provides special support for the string * concatenation operator ( + ), and for conversion of * other objects to strings. String concatenation is implemented * through the {@code StringBuilder}(or {@code StringBuffer}) * class and its {@code append} method. * String conversions are implemented through the method * {@code toString}, defined by {@code Object} and * inherited by all classes in Java. For additional information on * string concatenation and conversion, see Gosling, Joy, and Steele, * <i>The Java Language Specification</i>. |
String 類代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作為此類的實例實現。 字符串是常量;它們的值在創建之后不能更改。字符串緩沖區支持可變的字符串。因為 String 對象是不可變的,所以可以共享。例如: 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); String 類包括的方法可用于檢查序列的單個字符、比較字符串、搜索字符串、提取子字符串、創建字符串副本并將所有字符全部轉換為大寫或小寫。大小寫映射基于 Character 類指定的 Unicode 標準版。 Java 語言提供對字符串串聯符號("+")以及將其他對象轉換為字符串的特殊支持。字符串串聯是通過 StringBuilder(或 StringBuffer)類及其 append 方法實現的。字符串轉換是通過 toString 方法實現的,該方法由 Object 類定義,并可被 Java 中的所有類繼承。有關字符串串聯和轉換的更多信息,請參閱 Gosling、Joy 和 Steele 合著的 The Java Language Specification。 |
1、String是個final類
2、String是不可變的字符序列
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
String對象的字符內容是存儲在一個字符數組中的。
private意味著外面無法直接獲取字符數組,而且String沒有提供value的get和set方法,
final意味著字符數組的引用不可改變,即通過讓value指向新的數組對象來實現修改String對象,
而且String也沒有提供方法來修改value數組某個元素值,因此字符串的字符數組內容也不可變。
疑問?那么字符串的拼接、字符串的截取、字符串的替換等操作是如何實現的呢?
每次修改都創建一個新的char數組表示修改結果。
3、String對象的創建
String str=“hello”;
String s1=new String(); // 本質上 this.value=new char[0];
String s2=new String(String original); //this.value=original.value;
String s3=new String(char[] a); //this.value=Arrays.copyOf(value, value.length);
String s4=new String(char[] a,int startIndex,int count)
.......
4、字符串對象是如何存儲的
字符串常量存儲在字符串常量池,目的是共享
字符串非常量對象存儲在堆中。
5、String的拼接
結論:
常量與常量的拼接結果在常量池
只要其中有一個是變量,結果就在堆中
如果拼接的結果調用intern()方法,就在常量池中
6、String對象的比較
==比較的是地址。
equals比較的是字符串的內容,重寫了Object的equals方法。
public boolean equals(Object anObject) {
if (this==anObject) {
return true;
}
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;
}
1、常用方法系列之一
l int length():返回字符串的長度: return value.length;
l boolean isEmpty():判斷是否是空字符串:return value.length==0;
l String toLowerCase():使用默認語言環境的規則將此 String 中的所有字符都轉換為小寫。
l String toUpperCase():使用默認語言環境的規則將此 String 中的所有字符都轉換為大寫。
l String trim():返回字符串的副本,忽略前導空白和尾部空白。
l boolean equals(Object obj):比較字符串的內容
l boolean equalsIgnoreCase(String anotherString):與equals方法類似,忽略大小寫
l String concat(String str):將指定字符串連接到此字符串的結尾。 等價于用“+”
2、String類和字符相關操作
l char charAt(int index): 返回某索引處的字符return value[index];
l char[] toCharArray():將此字符串轉換為一個新的字符數組
l String(char[] value):分配一個新的 String,使其表示字符數組參數中當前包含的字符序列。
l String(char[] value, int offset, int count):分配一個新的 String,它包含取自字符數組參數一個子數組的字符。
3、String類字節與字符串操作方法
編碼:把字符-->字節
l byte[] getBytes():使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。
l byte[] getBytes(Charset charset) :使用給定的 charset 將此 String 編碼到 byte 序列,并將結果存儲到新的 byte 數組。
l byte[] getBytes(String charsetName) :使用指定的字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。
解碼:把字節-->字符
l String(byte[] bytes) :通過使用平臺的默認字符集解碼指定的 byte 數組,構造一個新的 String。
l String(byte[] bytes, Charset charset):通過使用指定的 charset 解碼指定的 byte 數組,構造一個新的 String。
l String(byte[] bytes, int offset, int length) :通過使用平臺的默認字符集解碼指定的 byte 子數組,構造一個新的 String。
l String(byte[] bytes, int offset, int length, Charset charset):通過使用指定的 charset 解碼指定的 byte 子數組,構造一個新的 String。
l String(byte[] bytes, int offset, int length, String charsetName):通過使用指定的字符集解碼指定的 byte 子數組,構造一個新的 String。
l String(byte[] bytes, String charsetName):通過使用指定的 charset 解碼指定的 byte 數組,構造一個新的 String。
4、String類判斷是否以指定內容開頭或結尾
l boolean endsWith(String suffix):測試此字符串是否以指定的后綴結束。
l boolean startsWith(String prefix):測試此字符串是否以指定的前綴開始。
l boolean startsWith(String prefix, int toffset):測試此字符串從指定索引開始的子字符串是否以指定前綴開始。
5、String類字符串查找操作
l boolean contains(CharSequence s):當且僅當此字符串包含指定的 char 值序列時,返回 true。
l int indexOf(int ch):返回指定字符在此字符串中第一次出現處的索引。
l int indexOf(int ch, int fromIndex):返回在此字符串中第一次出現指定字符處的索引,從指定的索引開始搜索。
l int indexOf(String str):返回指定子字符串在此字符串中第一次出現處的索引。
l int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始。
l int lastIndexOf(int ch):返回指定字符在此字符串中最后一次出現處的索引。
l int lastIndexOf(int ch, int fromIndex):返回指定字符在此字符串中最后一次出現處的索引,從指定的索引處開始進行反向搜索。
l int lastIndexOf(String str):返回指定子字符串在此字符串中最右邊出現處的索引。
l int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出現處的索引,從指定的索引開始反向搜索。
indexOf和lastIndexOf方法如果未找到都是返回-1
6、String類字符串截取操作
l String substring(int beginIndex)
返回一個新的字符串,它是此字符串的從beginIndex開始截取到最后的一個子字符串。
l String substring(int beginIndex, int endIndex)
返回一個新字符串,它是此字符串從beginIndex開始截取到endIndex(不包含)的一個子字符串。
7、String類是否匹配正則
l boolean matches(String regex):告知此字符串是否匹配給定的正則表達式。
public static void main(String[] args) {
String str="12345";
//判斷str字符串中是否全部有數字組成,即有1-n個數字組成
boolean matches=str.matches("\\d+");
System.out.println(matches);
String tel="0571-4534289";
//判斷這是否是一個杭州的固定電話
boolean result=tel.matches("0571-\\d{7,8}");
System.out.println(result);
}
8、String類替換操作
l String replace(char oldChar, char newChar):
返回一個新的字符串,它是通過用 newChar 替換此字符串中出現的所有 oldChar 得到的。
l String replace(CharSequence target, CharSequence replacement):
使用指定的字面值替換序列替換此字符串所有匹配字面值目標序列的子字符串。
l String replaceAll(String regex, String replacement):
使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串。
l String replaceFirst(String regex, String replacement):
使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串。
public static void main(String[] args) {
String str="12hello34world5java7891mysql456";
//把字符串中的數字替換成,,如果結果中開頭和結尾有,的話去掉
String string=str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);
}
9、String類字符串拆分操作
l String[] split(String regex):根據給定正則表達式的匹配拆分此字符串。
l String[] split(String regex, int limit):根據匹配給定的正則表達式來拆分此字符串,最多不超過limit個,如果超過了,剩下的全部都放到最后一個元素中。
public static void main(String[] args) {
String str="hello|world|java";
String[] strings=str.split("\\|");
for (String string : strings) {
System.out.println(string);
}
String str2="hello.world.java";
String[] strings2=str2.split("\\.");
for (String string : strings2) {
System.out.println(string);
}
}
往期精彩內容:
Java常用類_包裝類Wrapper
我們考慮以下多行SQL字符串:
UPDATE "public"."office"
SET ("address_first", "address_second", "phone")=(SELECT "public"."employee"."first_name",
"public"."employee"."last_name", ?
FROM "public"."employee"
WHERE "public"."employee"."job_title"=?
眾所周知,在JDK 8之前,我們可以以多種方式將這段SQL包裝成Java字符串(字符串字面量)。
在JDK 8之前
可能最常見的方法是使用眾所周知的"+"運算符進行直接連接。這樣,我們得到如下的多行字符串表示:
String sql="UPDATE \"public\".\"office\"\n"
+ "SET (\"address_first\", \"address_second\", \"phone\")=\n"
+ " (SELECT \"public\".\"employee\".\"first_name\",\n"
+ " \"public\".\"employee\".\"last_name\", ?\n"
+ " FROM \"public\".\"employee\"\n"
+ " WHERE \"public\".\"employee\".\"job_title\"=?";
編譯器應該(并且通常是)足夠智能,將"+"操作內部轉換為StringBuilder/StringBuffer實例,并使用append()方法來構建最終的字符串。但是,我們可以直接使用StringBuilder(非線程安全)或StringBuffer(線程安全),如以下示例所示:
StringBuilder sql=new StringBuilder();
sql.append("UPDATE \"public\".\"office\"\n")
.append("SET ...\n")
.append(" (SELECT...\n")
// ... 省略其他部分
另一種方法(可能不如前兩種流行)是使用String.concat()方法。這是一個不可變操作,基本上將給定的字符串附加到當前字符串的末尾。最后,它返回新的組合字符串。嘗試附加null值將導致NullPointerException(在前面的兩個示例中,我們可以附加null值而不會引發任何異常)。通過鏈接concat()調用,我們可以像以下示例一樣表示多行字符串:
String sql="UPDATE \"public\".\"office\"\n"
.concat("SET...\n")
.concat(" (SELECT...\n")
// ... 省略其他部分
進一步來說,我們有String.format()方法。只需使用%s格式說明符,我們就可以在多行字符串中連接多個字符串(包括null值),如下所示:
String sql=String.format("%s%s%s%s%s%s",
"UPDATE \"public\".\"office\"\n",
"SET ...\n",
" (SELECT ...\n",
// ... 省略其他部分
雖然這些方法如今仍然很流行,但讓我們看看JDK 8在這個話題上有什么要說的。
從JDK 8開始
從JDK 8開始,我們可以使用String.join()方法來表示多行字符串。此方法也專門用于字符串連接,它允許我們的示例具有清晰的可讀性。如何實現?此方法將分隔符作為第一個參數,并在要連接的字符串之間使用此分隔符。因此,如果我們認為\n是我們的行分隔符,那么它只需要指定一次,如下所示:
String sql=String.join("\n",
"UPDATE \"public\".\"office\"",
"SET (\"address_first\", \"address_second\", \"phone\")=",
" (SELECT \"public\".\"employee\".\"first_name\",",
" \"public\".\"employee\".\"last_name\", ?",
" FROM \"public\".\"employee\"",
" WHERE \"public\".\"employee\".\"job_title\"=?;");
除了String.join()方法外,JDK 8還提供了java.util.StringJoiner。StringJoiner支持分隔符(如String.join())但也支持前綴和后綴。表達我們的多行SQL字符串不需要前綴/后綴;因此分隔符仍然是我們最喜歡的功能:
StringJoiner sql=new StringJoiner("\n");
sql.add("UPDATE \"public\".\"office\"")
.add("SET (\"address_first\", ..., \"phone\")=")
.add(" (SELECT \"public\".\"employee\".\"first_name\",")
// ... 省略其他部分
最后,談到JDK 8就不能不提它的強大的Stream API。更具體地說,我們對Collectors.joining()收集器感興趣。這個收集器的工作方式與String.join()相同,在我們的例子中,它看起來像這樣:
String sql=Stream.of(
"UPDATE \"public\".\"office\"",
"SET (\"address_first\", \"address_second\", \"phone\")=",
" (SELECT \"public\".\"employee\".\"first_name\",",
" \"public\".\"employee\".\"last_name\", ?",
" FROM \"public\".\"employee\"",
" WHERE \"public\".\"employee\".\"job_title\"=?;")
.collect(Collectors.joining(String.valueOf("\n")));
所有前面的示例都有一個共同的缺點。最重要的是,這些示例中沒有一個是真正的多行字符串字面量,每行之間的轉義字符和額外引號嚴重影響了可讀性。幸運的是,從JDK 13(作為未來預覽)到JDK 15(作為最終功能),新的文本塊已成為表示多行字符串字面量的標準。讓我們看看如何實現。
引入文本塊(JDK 13/15)
JDK 13(JEP 355)引入了一個預覽功能,旨在為多行字符串字面量提供支持。在JDK 15(JEP 378)的兩個版本中,文本塊功能已成為最終且永久可用的功能。但是,讓我們快速看看文本塊如何塑造我們的多行SQL字符串:
String sql="""
UPDATE "public"."office"
SET ("address_first", "address_second", "phone")= (SELECT "public"."employee"."first_name",
"public"."employee"."last_name", ?
FROM "public"."employee"
WHERE "public"."employee"."job_title"=?""";
這太棒了,對吧?!我們立即注意到SQL的可讀性已經恢復,我們沒有混淆分隔符、行終止符和連接。文本塊簡潔、易于更新且易于理解。在SQL字符串中額外的代碼足跡為零,Java編譯器將盡最大努力以盡可能可預測的方式創建字符串。以下是嵌入JSON信息的另一個示例:
String json="""
{
"widget": {
"debug": "on",
"window": {
"title": "Sample Widget 1",
"name": "back_window"
},
// ... 省略其他部分
}""";
那么,如何用文本塊表示HTML呢?
String html="""
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
<!-- 這里有一個錯誤,缺少年齡單元格 -->
</tr>
</table>"""; // 注意這里修正了原始代碼中的錯誤,應該是</table>而不是<table>
掛接文本塊語法
文本塊的語法相當簡單。沒有花哨的東西,也沒有復雜的事情,只需要記住兩個方面:
1. 文本塊必須以"""(即三個雙引號)和換行符開始。我們稱此構造為開放分隔符。
2. 文本塊必須以"""(即三個雙引號)結束。"""可以單獨放在一行(作為新行)或放在文本的最后一行末尾(如我們的示例所示)。我們稱此構造為關閉分隔符。但是,這兩種方法之間存在語義差異(在下一個問題中詳細討論)。
在此上下文中,以下示例在語法上是正確的:
String tb="""
I'm a text block""";
String tb="""
I'm a text block
""";
// ... 其他正確示例
另一方面,以下示例是不正確的,并會導致編譯器錯誤:
String tb="""I'm a text block"""; // 錯誤:缺少換行符
// ... 其他錯誤示例
但是,請考慮以下最佳實踐。
通過查看前面的代碼片段,我們可以為文本塊塑造一個最佳實踐:僅在您有多行字符串時使用文本塊;如果字符串適合單行代碼(如前面的代碼片段所示),則使用普通字符串字面量,因為使用文本塊不會增加任何顯著價值。
在捆綁的代碼中,您可以在SQL、JSON和HTML的片段上實踐本問題中的所有示例。
對于第三方庫支持,請考慮:Apache Commons, StringUtils.join(), 和 Guava Joiner.on()。
接下來,讓我們專注于處理文本塊分隔符。
JavaScript 字符串用于存儲和處理文本。
JavaScript 字符串
字符串可以存儲一系列字符,如 "John Doe"。
字符串可以是插入到引號中的任何字符。你可以使用單引號或雙引號:
實例
var carname="Volvo XC60";
var carname='Volvo XC60';
你可以使用索引位置來訪問字符串中的每個字符:
實例
var character=carname[7];
字符串的索引從 0 開始,這意味著第一個字符索引值為 [0],第二個為 [1], 以此類推。
你可以在字符串中使用引號,字符串中的引號不要與字符串的引號相同:
實例
var answer="It's alright";
var answer="He is called 'Johnny'";
var answer='He is called "Johnny"';
你也可以在字符串添加轉義字符來使用引號:
實例
var x='It\'s alright';
var y="He is called \"Johnny\"";
字符串長度
可以使用內置屬性 length 來計算字符串的長度:
實例
var txt="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sln=txt.length;
特殊字符
在 JavaScript 中,字符串寫在單引號或雙引號來中。
因為這樣,以下實例 JavaScript 無法解析:x
"We are the so-called "Vikings" from the north."
字符串 "We are the so-called " 被截斷。
如何解決以上的問題呢?可以使用反斜杠 (\) 來轉義 "Vikings" 字符串中的雙引號,如下:
"We are the so-called \"Vikings\" from the north."
反斜杠是一個轉義字符。 轉義字符將特殊字符轉換為字符串字符:
轉義字符 (\) 可以用于轉義撇號,換行,引號,等其他特殊字符。
下表中列舉了在字符串中可以使用轉義字符轉義的特殊字符:
代碼 | 輸出 |
---|---|
\' | 單引號 |
\" | 雙引號 |
\ | 反斜杠 |
\n | 換行 |
\r | 回車 |
\t | tab(制表符) |
\b | 退格符 |
\f | 換頁符 |
字符串可以是對象
通常, JavaScript 字符串是原始值,可以使用字符創建: var firstName="John"
但我們也可以使用 new 關鍵字將字符串定義為一個對象: var firstName=new String("John")
實例
var x="John";
var y=new String("John");
typeof x // 返回 String
typeof y // 返回 Object
不要創建 String 對象。它會拖慢執行速度,并可能產生其他副作用: |
實例
var x="John";
var y=new String("John");
(x===y) // 結果為 false,因為是字符串,y 是對象
===為絕對相等,即數據類型與值都必須相等。
字符串屬性和方法
原始值字符串,如 "John", 沒有屬性和方法(因為他們不是對象)。
原始值可以使用 JavaScript 的屬性和方法,因為 JavaScript 在執行方法和屬性時可以把原始值當作對象。
字符串屬性
屬性 | 描述 |
---|---|
constructor | 返回創建字符串屬性的函數 |
length | 返回字符串的長度 |
prototype | 允許您向對象添加屬性和方法 |
字符串方法
Method | 描述 |
---|---|
charAt() | 返回指定索引位置的字符 |
charCodeAt() | 返回指定索引位置字符的 Unicode 值 |
concat() | 連接兩個或多個字符串,返回連接后的字符串 |
fromCharCode() | 將 Unicode 轉換為字符串 |
indexOf() | 返回字符串中檢索指定字符第一次出現的位置 |
lastIndexOf() | 返回字符串中檢索指定字符最后一次出現的位置 |
localeCompare() | 用本地特定的順序來比較兩個字符串 |
match() | 找到一個或多個正則表達式的匹配 |
replace() | 替換與正則表達式匹配的子串 |
search() | 檢索與正則表達式相匹配的值 |
slice() | 提取字符串的片斷,并在新的字符串中返回被提取的部分 |
split() | 把字符串分割為子字符串數組 |
substr() | 從起始索引號提取字符串中指定數目的字符 |
substring() | 提取字符串中兩個指定的索引號之間的字符 |
toLocaleLowerCase() | 根據主機的語言環境把字符串轉換為小寫,只有幾種語言(如土耳其語)具有地方特有的大小寫映射 |
toLocaleUpperCase() | 根據主機的語言環境把字符串轉換為大寫,只有幾種語言(如土耳其語)具有地方特有的大小寫映射 |
toLowerCase() | 把字符串轉換為小寫 |
toString() | 返回字符串對象值 |
toUpperCase() | 把字符串轉換為大寫 |
trim() | 移除字符串首尾空白 |
valueOf() | 返回某個字符串對象的原始值 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。