【Java常用类】1-3 String 类

§1-3 String

1-3.1 String 概述

在基础课,我们早已接触 String 类。String 类并不属于八大基本类型之一,而属于类。

首先来看看 String 类的一些特点:

  • 字符串的字面值存储在字符串池中,可以共享;
  • 字符串是常量,创建之后不可改变;
  • 使用赋值方式创建 String 对象时,字符串会在字符串池中存储;
  • 使用 new 语句创建 String 对象时,会产生两个对象:堆、字符串池中各存储一个。使用这种方式创建对象较浪费空间;
  • 根据 JDK 版本的不同,字符串池可能在堆中,也可能在方法区中,因版本而异。

String 适合用于操作量较少时的情况。

解释

使用赋值语句创建字符串:

String str1 = "Hello";
str1 = "world";
String str2 = str1;

运行时,首先会在字符串池中查找是否存在该字符串。若没有,则在池中创建该字符串,并让引用指向该地址。

然后,str1 的值 “发生改变”,实际上,池中创建了一个新的字符串,内容是 world,并让栈中的引用 str1 指向池中的 world。此时,Hello 被废弃,若无更多引用,触发垃圾回收器则可能会触发回收。

从这一点上看,字符串是常量,创建后不可改变。看似改变其值的语句,实际上是在更改引用的指向。

str2 = str1,二者共同指向池中相同的字符串。使用 == 运算符可比较引用指向地址是否相同:

System.out.println(str1 == str2);

得到:

true

二者共同指向池中的 Hello

使用 new 创建字符串:

String str3 = new String("Java");
String str4 = new String("Java");

使用 new 语句,则仅会在池中创建对象,堆中也会创建对象,存储内容都是池中共同且唯一的 "Java"。此时,栈中的引用变量分别指向堆中不同的对象,但堆中不同的对象所存储内容实际上都来自池中相同的字符串。使用 == 运算符,可用于比较引用的地址是否相同:

System.out.println(str3 == str4);

得到:

false

二者分别指向堆中的不同对象。

由此可见,比较字符串内容时,通常使用 equals() 方法。由于 String 类重写了 Object 类的 equals() 方法,使得这一操作变为可行。

1-3.2 常用方法

String 类中的一些常用方法如下:

1-3.2.1 equals(Object obj);equalsIgnoreCase(String str);

equals(Obj obj);:将此字符串与指定对象进行比较。此处不再赘述。

equalsIgnoreCase(String str):将此字符串与另一个字符串作比较,忽略大小写。

1-3.2.2 compareTo(String str);compareToIgnoreCase(String str);

compareTo(String str);:按字典顺序比较两个字符串。

compareToIgnoreCase(String str);:按字典顺序比较两个字符串,忽略大小写。

示例:该方法比较的是第一个出现差异的字符的编码,返回二者编码之差。

String str1 = "abc";	//a -> 97
String str2 = "xyz";	//x ->120
String str3 = "abcxyz";
System.out.println(str1.compareTo(str2));	//97 - 120 = -23
System.out.println(str9.compareTo(str11));  //长度不等,但前面相同,比较长度

得到

-23
-3

1-3.2.3 length();

描述:返回此字符串的长度。

示例

String str = "Hello";
System.out.println(str.length());

得到

5

1-3.2.4 isEmpty();isBlank();

isEmpty();:判断字符串是否为空,当且仅当 length() == 0 时返回 true

isBlank();:判断字符串是否仅含有空白字符,当字符串为空或仅含有空白字符时返回 true

示例

String str;
str = "";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());
str = "\r\n";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());
str = "Hello";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());

得到

str5.isEmpty() = true
str5.isBlank() = true
str5.isEmpty() = false
str5.isBlank() = true
str5.isEmpty() = false
str5.isBlank() = false

1-3.2.5 charAt(int index);

描述:返回指定索引(下标)处的字符。

示例

String str = "Hello";
System.out.println(str.charAt(1));
System.out.println(str.charAt(str.length() - 1));

得到:

e
o

注意:下标越界会抛出异常 StringIndexOutOfBoundsException,其父类是 IndexOutOfBoundsException,均属于运行时异常(RuntimeException)。

1-3.2.6 codePointAt(int index);

描述:返回指定索引处的字符(Unicode 代码点)

示例

String str = "你好世界!";
System.out.println("索引 0 处的 Unicode 代码点:" + str2.codePointAt(0));

得到:

索引 0 处的 Unicode 代码点:20320

什么是代码点

引用自 java中codepoint是什么?_Jobs_orz的博客-CSDN博客

Unicode 字符集中,每一个字符对应一个 codepoint,即代码点。Java 的 char 占用 2 字节,总共只能表示 \(2^{16} = 65536\) 种字符,远少于 Unicode 中的字符数。这时候需要两个 char 才能表示一个 Unicode 字符了,此时,codepoint 就是对应两个 char 所表示的一个字符。

1-3.2.7 contains(String str);

描述:判断当前字符串中是否包含 str

示例

String str = "Java is the best programming language.";
System.out.println(str.contains("php"));

得到:

false

1-3.2.8 toCharArray();

描述:将字符串转换为新的字符数组。

示例

String str = "Hello world!";
char[] chs = str.toCharArray();
System.out.println("字符数组 str: " + Arrays.toString(chs));

得到:

字符数组 str: [H, e, l, l, o,  , w, o, r, l, d, !]

1-3.2.9 trim();

描述:删除字符串前后的空格,其中空格定义为代码点小于或等于 'U+0020'(空格字符)的任何字符。

示例

String str = "   博客园   ";
System.out.println("原始字符串:" + str);
System.out.println("处理后字符串:" + str.trim());

得到:

原始字符串:   博客园   
处理后字符串:博客园

1-3.2.10 indexOf();lastIndexOf();

indexOf(String str);:返回指定子字符串在该字符串中第一次出现的索引。

lastIndexOf(String str);:返回最后一次出现的指定子字符串在此字符串中的索引。

示例

String str = "Hello world!";
//找不到则返回 -1
System.out.println("str 中首次出现 l 的索引:" + str.indexOf("l"));
System.out.println("str 中最后出现 l 的索引:" + str.lastIndexOf("l"));
System.out.println("str 中首次出现 z 的索引:" + str.indexOf('z'));
System.out.println(sep);

得到:

str 中首次出现 l 的索引:2
str 中最后出现 l 的索引:9
str 中首次出现 z 的索引:-1

该方法的其他重载:

方法 行为
public int indexOf(String str); 返回指定子字符串在该字符串中第一次出现的索引
public int indexOf(String str, int fromIndex); 从指定索引开始,返回第一次出现的指定子字符串在此字符串中的索引
public int indexOf(int ch); 返回指定字符在此字符串中第一次出现的索引
public int indexOf(int ch, int fromIndex); 返回指定字符在此字符串中第一次出现的索引,从指定索引处开始搜索
public int lastIndexOf(String str); 返回最后一次出现的指定子字符串在此字符串中的索引
public int lastIndexOf(String str, int fromIndex); 返回最后一次出现的指定子字符串在此字符串中的索引,从指定索引开始向后搜索
public int lastIndexOf(int ch); 返回最后一次出现的指定字符在此字符串中的索引
public int lastIndexOf(int ch, int fromIndex); 返回最后一次出现的指定字符在此字符串中的索引,从指定索引开始向后搜索

1-3.2.11 startsWith();endsWith(String suffix);

startsWith();:测试此字符串是否以指定前缀开头。

endsWith();:测试此字符串是否以指定的后缀结尾。

示例

String str1 = "Hello world!";
String str2 = "你好世界!";

System.out.println("str1 是否以 Hello 为前缀?" + str1.startsWith("Hello"));
System.out.println("str2 是否以 Hello 为前缀?" + str2.startsWith("Hello"));
System.out.println("===============");

System.out.println("str1 是否以 world! 为后缀?" + str1.endsWith("world!"));
System.out.println("str2 是否以 ! 为后缀?" + str2.endsWith("!"));
System.out.println("===============");

得到:

str1 是否以 Hello 为前缀?true
str2 是否以 Hello 为前缀?false
===============
str1 是否以 world! 为后缀?true
str2 是否以 ! 为后缀?false
===============

startsWith();方法的其他重载版本:

方法 行为
public boolean startsWith(String prefix); 测试此字符串是否以指定前缀开头
public boolean startsWith(String prefix, int toffset); 测试从指定索引开始的此字符串的子字符串是否以指定前缀开头

1-3.2.12 toLowerCase();toUpperCase();

toLowerCase();:使用默认locale的规则将此 String 中的所有字符转换为小写。

toUpperCase();:使用默认locale的规则将此 String 中的所有字符转换为大写。

示例

String str = "Hello world!";
System.out.println("转换为全小写:" + str.toLowerCase());
System.out.println("转换为全大写:" + str.toUpperCase());

得到:

转换为全小写:hello world!
转换为全大写:HELLO WORLD!

该方法的其他重载版本:

方法 行为
public String toLowerCase(Locale locale); 使用给定 Locale 的规则将此 String 中的所有字符转换为小写
public String toUpperCase(Locale locale); 使用给定 Locale 的规则将此 String 中的所有字符转换为大写。

1-3.2.13 replace();replaceAll();

replace(char oldChar, char newChar);:返回将此字符串中所有出现的 oldChar 替换为 newChar 的字符串(替换字符)。

replace(CharSequence target, CharSequence replacement);:用给定的替换字符串,替换此字符串中与给定的 正则表达式 匹配的第一个子字符串。

replaceAll(String regex, String replacement);:用给定的替换替换此字符串中与给定的 正则表达式 匹配的每个子字符串。

CharSequenceString 类所实现的一个接口,利用多态,可以向 replace() 的第二个重载版本传入字符串。

replace();示例

String str = "Hello Java!";
System.out.println("替换前:" + str);
System.out.println("替换后:" + str.replace("Java", "PHP"));
System.out.println("再次输出原字符串:" + str);

得到

替换前:Hello Java!
替换后:Hello PHP!
再次输出原字符串:Hello Java!

replaceAll();示例:该方法传入参数支持正则表达式

String str = "Java是最好的编程语言,Java真香!";
System.out.println("原字符串:" + str);
System.out.println("替换全部:" + str.replaceAll("Java", "PHP"));

得到:

原字符串:Java是最好的编程语言,Java真香!
替换全部:PHP是最好的编程语言,PHP真香!

该方法的调用 str.replaceAll(regex, repl); 与下列语句所产生的结果完全相同:

Pattern.complile(regex).matcher(str).replaceAll(repl);

有关正则表达式,请见官方文档。

1-3.2.14 split(String regex);

描述:围绕给定正则表达式的匹配项拆分此字符串,返回一个字符串数组。

示例

String str1 = "foo:and:boo";
String str2 = "Java is the best programming language, Java is nice!";

System.out.println("原字符串:" + str1);
System.out.println("拆分此串:" + Arrays.toString(str1.split(":")));

System.out.println("原字符串:" + str2);
//使用正则表达式拆分:以 " "和","拆分
System.out.println("拆分此串:" + Arrays.toString(str2.split("[ ,]")));
System.out.println(sep);

得到:

原字符串:foo:and:boo
拆分此串:[foo, and, boo]
原字符串:Java is the best programming language, Java is nice!
拆分此串:[Java, is, the, best, programming, language, , Java, is, nice!]

该方法的其他重载版本:

方法 行为
public String[] split(String regex, int limit); 围绕给定的正则表达式拆分此字符串。

limit 参数用于控制应用 pattern 的次数,影响返回的数组的长度:

  • limit 为正数,则 pattern 会最多应用 limit - 1 次,所得数组长度将不大于 limit ,数组的最后一个条目将包含最后一个定界符(delimiter)之外的所有输入;
  • limit 为零,则 pattern 会尽可能多地应用,所得数组会拥有任意长度,尾随的空字符串将会被丢弃;
  • limit 为负数,则 pattern 会尽可能多地应用,所得数组会拥有任意长度。

以字符串 foo:and:boo 为例:

//正则表达式 ":"
String str = "foo:and:boo";
System.out.println("原字符串:" + str);
System.out.println("正则表达式\":\",限制 2:" + Arrays.toString(str.split(":", 2)));
System.out.println("正则表达式\":\",限制 5:" + Arrays.toString(str.split(":", 5)));
System.out.println("正则表达式\":\",限制 -2:" + Arrays.toString(str.split(":", -2)));
System.out.println("===============");
System.out.println("正则表达式\"o\",限制 5:" + Arrays.toString(str.split("o", 2)));
System.out.println("正则表达式\"o\",限制 -2:" + Arrays.toString(str.split("o", -2)));
System.out.println("正则表达式\"o\",限制 0:" + Arrays.toString(str.split("o", 0)));
System.out.println("===============");

得到

原字符串:foo:and:boo
正则表达式":",限制 2:[foo, and:boo]
正则表达式":",限制 5:[foo, and, boo]
正则表达式":",限制 -2:[foo, and, boo]
===============
正则表达式"o",限制 5:[f, , :and:b, , ]
正则表达式"o",限制 -2:[f, , :and:b, , ]
正则表达式"o",限制 0:[f, , :and:b]
===============

该方法的调用 str.split(regex, n); 与下列语句所产生的结果完全相同:

Pattern.complile(regex).split(str,n);

有关正则表达式,请见官方文档。

1-3.2.15 concat();

描述:将指定的字符串连接到此字符串的末尾。

示例

String str = "concat";
System.out.println("原字符串:" + str);
System.out.println("拼接后:" + str.concat("enation"));

得到

原字符串:Concat
拼接后:Concatenation

1-3.2.16 substring();

substring(int beginIndex);:返回一个字符串,该字符串是此字符串的子字符串。

substring(int beginIndex, int endIndex);:返回一个字符串,该字符串是此字符串的子字符串。子字符串从指定的 beginIndex 开始并扩展到索引 endIndex - 1 处的字符。因此子串的长度是 endIndex-beginIndex

注意

  • substring(int beginIndex); 实际上调用的是第二个重载:substring(beginIndex, length());
  • beginIndex 为负数,或 endIndex 大于此字符串长度,或者 beginIndex 大于 endIndex,则抛出异常 IndexOutOfBoundsException

1-3.3 案例演示

满足以下需求:对于字符串 String str = "this is a text";

  1. 将字符串中的单词单独获取出来;
  2. str 中的 "text" 替换为 "practice"
  3. "text" 前加上 "easy"
  4. 将每个单词的首字母改为大写。

实现

public class CaseDemo {
    public static void main(String[] args) {
        String str = "this is a text";

        //1. 单独提取每个单词
        String[] arr = str.split(" ");
        System.out.println(Arrays.toString(arr));
        System.out.println("===============");

        //2. 替换 text 为 practice
        String str1 = str.replace("text", "practice");
        System.out.println(str1);
        System.out.println("===============");

        //3. 在 text 前加上 easy
        String str2 = str.replace("text", "easy text");
        System.out.println(str2);
        System.out.println("===============");

        //4. 将单词首字母改为大写
        for (int i = 0; i < arr.length; i++) {
            //提取每个单词的首字母,利用包装类转换成大写
            char first = arr[i].charAt(0);
            char firstUpperCase = Character.toUpperCase(first);

            //拼接
            //substring()
            arr[i] = firstUpperCase + arr[i].substring(1);
        }
        String str3 = "";
        for (int i = 0; i < arr.length; i++) {
            str3 = str3.concat(arr[i] + " ");
        }
        str3.trim();
        System.out.println(str3);
    }
}

运行,得到

[this, is, a, text]
===============
this is a practice
===============
this is a easy text
===============
This Is A Text 
posted @ 2023-07-19 12:07  Zebt  阅读(31)  评论(0)    收藏  举报