String

1. String类概述

String类是Java编程中用于表示文本字符串的一种数据类型。它可以存储任意长度的文本,可用于表示URL、文件路径、XML、HTML等各种文本数据。

String类是一个final类,因此它的值一旦确定就无法修改。它实现了SerializableCharSequenceComparable接口。

2. String类的创建

2.1 直接赋值

字符串可以直接在双引号内赋值。例如:

1
String str1 = "Hello, world!";

2.2 使用new关键字

也可以使用new关键字来创建一个字符串。例如:

1
String str2 = new String("Hello, world!");

2.3 使用字符串连接符

可以使用+号将多个字符串连接起来,形成一个新字符串。例如:

1
2
3
String str3 = "Hello, ";
String str4 = "world!";
String str5 = str3 + str4;

3. String类的方法

大小写

在 Java 中,String 类默认是不可变的,也就是说它的值一旦创建就不能被修改。因此,String 类并没有提供直接修改大小写的方法。

然而,你可以使用以下方法来实现大小写转换:

  1. 使用 toLowerCase() 方法将字符串转换为小写形式:

    1
    2
    3
    String str = "Hello World";
    String lowercaseStr = str.toLowerCase(); // 将字符串转换为小写形式
    System.out.println(lowercaseStr); // 输出:hello world
  2. 使用 toUpperCase() 方法将字符串转换为大写形式:

    1
    2
    3
    String str = "Hello World";
    String uppercaseStr = str.toUpperCase(); // 将字符串转换为大写形式
    System.out.println(uppercaseStr); // 输出:HELLO WORLD

请注意,这些方法会创建一个新的字符串对象,而不会修改原始的字符串。

如果你需要在程序中频繁修改字符串的大小写,可以考虑使用 StringBuilder 或 StringBuffer,它们提供了一些更高效的方法来修改字符串。

比较字符串

在Java中,比较字符串有两种常用的方法:使用equals()方法和使用compareTo()方法。

  1. 使用equals()方法进行字符串比较:

    equals()方法是String类提供的用于比较字符串内容的方法。它会比较两个字符串的每一个字符,并返回一个布尔值,表示两个字符串是否相等。

    1
    2
    3
    4
    String str1 = "Hello";
    String str2 = "World";

    boolean equal = str1.equals(str2); // false

    在上面的例子中,str1str2的内容不相等,因此equals()方法返回false

    需要注意的是,equals()方法区分大小写。如果需要忽略大小写进行比较,可以使用equalsIgnoreCase()方法。

  2. 使用compareTo()方法进行字符串比较:

    compareTo()方法是String类提供的用于比较字符串大小关系的方法。它比较两个字符串的字典顺序,并返回一个整数值来表示比较结果。

    1
    2
    3
    4
    String str1 = "Hello";
    String str2 = "World";

    int result = str1.compareTo(str2); // -15

    在上面的例子中,compareTo()方法返回一个负整数,表示str1在字典顺序中排在str2之前。

    compareTo()方法返回值的含义如下:

    • 如果返回值为负数,表示调用者字符串小于传入的字符串。
    • 如果返回值为零,表示两个字符串相等。
    • 如果返回值为正数,表示调用者字符串大于传入的字符串。

    需要注意的是,compareTo()方法区分大小写。如果需要忽略大小写进行比较,可以使用compareToIgnoreCase()方法。

截取

在Java的String类中,可以使用substring()方法来实现字符串的截取。该方法有两个重载形式:

  1. substring(int beginIndex):从指定的索引位置开始截取字符串到结尾。
  2. substring(int beginIndex, int endIndex):从指定的索引位置开始截取字符串,直到指定的结束索引位置,但不包括结束位置的字符。

下面是几个示例:

1
2
3
4
String str = "Hello, World!";
String substring1 = str.substring(7); // "World!"
String substring2 = str.substring(0, 5); // "Hello"
String substring3 = str.substring(7, str.length()); // "World!"

在上面的例子中,我们使用substring()方法截取了不同范围的字符串。

  • 在第一个示例中,从索引位置7开始截取到结尾,得到字符串”World!”。
  • 在第二个示例中,从索引位置0开始截取到索引位置5(不包括索引位置5),得到字符串”Hello”。
  • 在第三个示例中,从索引位置7开始截取到字符串的长度(结尾),得到字符串”World!”。

需要注意的是,截取操作并不会改变原始字符串的值,而是返回一个新的字符串。

另外,如果传入的索引位置超出了字符串的范围,会抛出IndexOutOfBoundsException异常。因此,在使用substring()方法时,要确保传入的索引位置在有效的范围内。

拼接

在Java的String类中,可以使用”+”运算符或者concat()方法来实现字符串的拼接。

  1. 使用”+”运算符进行字符串拼接:

    可以使用”+”运算符将两个字符串进行拼接,并返回拼接后的新字符串。

    1
    2
    3
    4
    String str1 = "Hello";
    String str2 = "World";

    String result = str1 + " " + str2; // "Hello World"

    在上面的例子中,”+”运算符将str1、空格和str2进行拼接,得到新的字符串”Hello World”。

  2. 使用concat()方法进行字符串拼接:

    String类还提供了concat()方法,可以将指定的字符串连接到调用者字符串的末尾,并返回拼接后的新字符串。

    1
    2
    3
    4
    String str1 = "Hello";
    String str2 = "World";

    String result = str1.concat(" ").concat(str2); // "Hello World"

    在上面的例子中,先使用concat()方法将空格拼接到str1的末尾,然后再将str2拼接到末尾,得到新的字符串”Hello World”。

无论是使用”+”运算符还是concat()方法,拼接操作都不会改变原始字符串的值,而是返回一个新的拼接后的字符串。

需要注意的是,使用”+”运算符拼接字符串时,底层实际上是调用了StringBuilder类来进行拼接操作。因此,在进行大量拼接操作时,使用StringBuilder的append()方法可能更高效。

获取字符数量

在Java的String类中,要获取字符串的长度,可以使用length()方法。这个方法返回字符串的字符数量,也就是字符串的长度。

下面是一个示例:

1
2
3
String str = "Hello, World!";
int length = str.length();
System.out.println(length); // 输出 13

需要注意的是,长度指的是字符串中字符的数量,而不是内存空间的大小。这意味着即使字符串中有一些特殊字符或者Unicode字符,length()方法返回的结果也是它们在字符串中的实际数量,而不是它们在内存中占用的字节数。

获取指定位置的字符

在Java的String类中,你可以使用charAt()方法来获取指定位置的字符。这个方法接受一个整数参数,代表了要获取的字符在字符串中的索引,然后返回该位置上的字符。

下面是一个用法示例:

1
2
3
String str = "Hello";
char ch = str.charAt(1);
System.out.println(ch); // 输出 e

需要注意的是,如果你传递给charAt()方法的索引超出了字符串的有效范围,将会抛出StringIndexOutOfBoundsException异常。因此,在使用charAt()方法时,需要谨慎确保索引的有效性。

查找字符

在Java的String类中,你可以使用indexOf()方法来查找指定字符在字符串中第一次出现的位置。该方法接受一个字符作为参数,并返回字符在字符串中的索引,如果没有找到指定的字符,则返回-1。

另外,Java的String类也提供了lastIndexOf()方法来查找指定字符在字符串中最后一次出现的位置。这个方法同样接受一个字符作为参数,并返回字符在字符串中最后一次出现的位置的索引,如果没有找到指定的字符,则返回-1。

下面是这两个方法的用法示例:

1
2
3
4
5
String str = "Hello, World!";
int firstIndex = str.indexOf('o');
int lastIndex = str.lastIndexOf('o');
System.out.println(firstIndex); // 输出 4
System.out.println(lastIndex); // 输出 8

在上面的示例中,我们使用了indexOf()方法和lastIndexOf()方法分别查找了字符串”Hello, World!”中字符’o’第一次出现的位置和最后一次出现的位置,并将结果打印出来。

如果你想要查找字符在字符串中所有出现的位置,你可能需要使用循环结合indexOf()方法来实现。当然,Java的String类也提供了其他更复杂的查找方法,比如contains()方法用于检查是否包含某个字符,matches()方法用于正则表达式匹配等。

替换字符

在Java的String类中,你可以使用replace()方法来替换字符串中的字符或者子串。这个方法接受两个参数,第一个参数是需要被替换的字符或者子串,第二个参数是用来替换的新字符或者新子串。

下面是一个使用replace()方法的示例:

1
2
3
String str = "Hello, World!";
String newStr = str.replace('o', 'x');
System.out.println(newStr); // 输出 Hellx, Wxrld!

在上面的示例中,我们使用了replace()方法将字符串”Hello, World!”中的字符’o’替换为’x’,然后将替换后的新字符串打印出来。

如果你想替换的是一个子串,也可以使用replace()方法。例如:

1
2
3
String str = "Hello, World!";
String newStr = str.replace("World", "Universe");
System.out.println(newStr); // 输出 Hello, Universe!

在上面的代码中,我们使用了replace()方法将字符串”Hello, World!”中的子串”World”替换为”Universe”,然后将替换后的新字符串打印出来。

需要注意的是,调用replace()方法并不会改变原始的字符串,它会返回一个新的字符串作为替换后的结果。

代码单元、代码点

在Java的String类中,字符串被存储为一个由Unicode字符序列组成的数组。在Java中,字符使用UTF-16编码,每个字符由一个或两个代码单元(code unit)表示。

  1. 代码单元(Code unit):代码单元是指UTF-16编码中的最小单位,每个代码单元占用16位(2个字节)的存储空间。对于大部分字符,一个代码单元就足够表示,但对于一些特殊字符(例如Emoji表情符号),需要使用两个代码单元来表示。在String类中,可以通过charAt()方法获取指定索引位置的代码单元。

    1
    2
    String str = "Hello";
    char codeUnit = str.charAt(1); // 获取索引为1的代码单元,结果为'e'
  2. 代码点(Code point):代码点是指Unicode代码空间中的一个位置,每个代码点对应一个字符。在Java中,可以使用codePointAt()方法获取指定索引位置的代码点。一个代码点可能由一个或多个代码单元组成。

    1
    2
    String str = "🌍Hello🌎";
    int codePoint = str.codePointAt(1); // 获取索引为1的代码点,结果为127757,对应字符'🌍'

“🌍Hello🌎” 解析

  1. “🌍” (地球表情符号): 这个字符由一个代码点组成 (U+1F30D),表示地球图标。

    • Unicode 代码点: U+1F30D
    • UTF-16 编码: 0xD83C 0xDF0D
  2. “H” (英文字母 H): 这是一个普通的 ASCII 字符,由一个代码点组成 (U+0048)。

  3. “e” (英文字母 e): 这也是一个普通的 ASCII 字符,由一个代码点组成 (U+0065)。

  4. “l” (英文字母 l): 这也是一个普通的 ASCII 字符,由一个代码点组成 (U+006C)。

  5. “l” (英文字母 l): 这也是一个普通的 ASCII 字符,由一个代码点组成 (U+006C)。

  6. “o” (英文字母 o): 这也是一个普通的 ASCII 字符,由一个代码点组成 (U+006F)。

  7. “🌎” (地球表情符号): 这个字符由一个代码点组成 (U+1F30E),表示地球图标。

    • Unicode 代码点: U+1F30E
    • UTF-16 编码: 0xD83C 0xDF0E

综上所述,字符串 “🌍Hello🌎” 包含了 7 个不同的代码点。需要注意的是,地球表情符号是由两个代码单元 (UTF-16 编码) 组成的,而其他的字符都是由一个代码单元表示的。此外,这个字符串中融合了不同语言的字符和表情符号,展示了 Unicode 字符编码的多样性。

代码点方法解析

  1. codePointAt(int index):

    • codePointAt 方法返回给定索引位置的代码点(Unicode 字符)。
    • 传入的索引值表示要访问的位置,可以是合法的索引范围内的任何位置。
    • 注意,对于代理对(surrogate pair)这样的扩展字符,需要使用两个代码单元(高低代理对)来表示一个代码点。
    • 如果索引越界或不合法,此方法将引发 IndexOutOfBoundsException 异常。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class StringTest {
    public static void main(String[] args) {
    String str = "🌍Hello🌎";
    for (int i = 0; i < str.length(); i++) {
    int codePoint = str.codePointAt(i); // 返回 U+1F30D
    String chat = new String(Character.toChars(codePoint));
    System.out.println("索引(" + i + ")对应代码点是:" + codePoint + " 字符是:" + chat);
    }
    }
    }

    输出结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    索引(0)对应代码点是:127757 字符是:🌍
    索引(1)对应代码点是:57101 字符是:?
    索引(2)对应代码点是:72 字符是:H
    索引(3)对应代码点是:101 字符是:e
    索引(4)对应代码点是:108 字符是:l
    索引(5)对应代码点是:108 字符是:l
    索引(6)对应代码点是:111 字符是:o
    索引(7)对应代码点是:127758 字符是:🌎
    索引(8)对应代码点是:57102 字符是:?
  2. codePointCount(int beginIndex, int endIndex):

    • codePointCount 方法返回指定索引范围内的代码点数量。
    • 传入的索引范围是从开始索引(包括)到结束索引(不包括)之间的范围。
    • 引入这个方法的目的是为了处理字符串中可能包含的代理对和其他 Unicode 字符。
    • 当计算代码点数量时,会自动将代理对视为一个代码点。
    1
    2
    3
    4
    5
    6
    public class StringTest {
    public static void main(String[] args) {
    String str = "🌍Hello🌎";
    System.out.println("(🌍Hello🌎)有" + str.codePointCount(0, str.length()) + "个代码点");
    }
    }

    输出结果:

    1
    (🌍Hello🌎)有7个代码点
  3. codePointBefore(int index):

    • codePointBefore 方法返回给定索引位置之前一个代码点的值。
    • 如果在给定索引位置之前存在代理对的低代理项,则返回对应的 Unicode 代码点。
    • 如果给定索引位置之前没有代码点,或者在开始索引位置,则此方法将引发 IndexOutOfBoundsException 异常。
    1
    2
    3
    4
    5
    String str = "🌍Hello🌎";
    int codePointBefore = str.codePointBefore(2);
    System.out.println("代码点:" + codePointBefore); // 输出:127757
    String codePointString = new String(new int[]{codePointBefore}, 0, 1);
    System.out.println("字符:" + codePointString); // 输出:🌍

    输出结果:

    1
    2
    代码点:127757
    字符:🌍
  4. length():

    • length 方法返回字符串的代码单元数量(UTF-16 编码的代码单元个数)。
    • 对于 ASCII 字符和大多数常见的非 ASCII 字符,一个字符对应一个代码单元。
    • 对于代理对和其他 Unicode 符号,一个字符可能对应两个代码单元(即一个扩展字符)。
    1
    2
    3
    String str = "🌍Hello🌎";
    int length = str.length(); // 返回 9
    System.out.println("(🌍Hello🌎)的长度为:" + length);

    输出结果:

    1
    (🌍Hello🌎)的长度为:9
  5. offsetByCodePoints(int index, int codePointOffset):

    • offsetByCodePoints 方法返回从给定索引位置开始,偏移指定的代码点数量后的索引位置。
    • 这个方法主要用于处理代码点之间的偏移,考虑到代理对的情况。
    • index 指定要偏移的起始索引,codePointOffset 指定要偏移的代码点数量。
    • 如果偏移数量是正数,则索引向后移动;如果偏移数量是负数,则索引向前移动。
    • 如果计算得到的索引位置超出了字符串的有效范围,此方法将引发 IndexOutOfBoundsException 异常。
    1
    2
    3
    4
    5
    String str = "🌍Hello🌎";
    int index = 2; // 获取第三个代码点对应的字符,索引是从0开始的
    int codePoint = str.codePointAt(str.offsetByCodePoints(0, index)); // 获取指定索引位置的代码点
    String character = new String(Character.toChars(codePoint)); // 将代码点转换为对应的字符
    System.out.println("第三个代码点对应的字符是:" + character); // 输出指定代码点位置的字符

    输出结果:

    1
    第三个代码点对应的字符是:e

空串和NULL串

在Java中,String类对空字符串(也就是空串,长度为0的字符串)和null字符串(未初始化的字符串引用)有着不同的处理方式。

  1. 空串(Empty String):空串是指长度为0的字符串,可以使用双引号””表示。String类的方法可以对空串进行操作,比如获取长度、连接、查找子串等等。在处理空串时,不会引发空指针异常,因为空串的长度为0,所有的操作都能够正常进行。

    1
    2
    3
    4
    String emptyStr = "";
    int length = emptyStr.length(); // 获取空串的长度,结果为0
    String result = emptyStr + "Hello"; // 将空串与其他字符串连接,结果为"Hello"
    int index = emptyStr.indexOf("abc"); // 在空串中查找子串,结果为-1
  2. null串(Null String):null串是指未初始化的字符串引用,它不指向任何有效的字符串对象。如果尝试在null串上调用方法或者进行操作,就会引发空指针异常(NullPointerException)。因此,在对字符串进行操作之前,必须确保其不为null。

    1
    2
    3
    4
    5
    String nullStr = null;
    // 下面的代码会引发空指针异常
    int length = nullStr.length();
    String result = nullStr + "Hello";
    int index = nullStr.indexOf("abc");

在实际编程中,需要注意在使用String类的方法时,要确保字符串不为null。可以通过条件判断或者空指针检查来避免空指针异常的发生。