String类

String类字符串常量池


在 Java 中,字符串常量池(String Pool)是一个特殊的存储区域,用于存储字符串字面量(literal strings),以节省内存和提高性能。字符串常量池的概念在 Java 7 及以后的版本中有所变化,但基本原理相同。

字符串常量池的基本概念:

  1. 存储位置:在 Java 7 及之前,字符串常量池位于永久代(PermGen)中;从 Java 7u20 开始,字符串常量池被移动到了堆内存中。在 Java 8 及以后的版本中,永久代被元空间(Metaspace)取代。

  2. 字符串字面量:当程序中出现双引号括起来的字符串时,如 String s = "Hello";,这个字符串 "Hello" 会被存储在字符串常量池中。如果字符串常量池中已经存在相同的字符串,那么就会直接引用已有的字符串,而不是创建一个新的字符串实例。

  3. String s1 = "Hello";
    String s2 = "Hello";
    

    上述代码中,s1s2 都指向字符串常量池中的同一个 "Hello"。

  4. 字符串的不可变性:由于字符串是不可变的,因此,任何对字符串的修改都会创建一个新的字符串对象,而不是修改原有的字符串常量池中的字符串。

  5. 字符串常量池的回收:由于字符串常量池存储的是字符串字面量,当字符串不再被引用时,它们可以被垃圾回收器回收。

字符串常量池的实现细节:

  • 字符串字面量和 new 关键字:使用 new 关键字创建的字符串,如 String s = new String("Hello");,不会存储在字符串常量池中,而是在堆内存中创建一个新的字符串对象。

  • intern() 方法intern() 方法可以将一个字符串对象放入字符串常量池中。如果常量池中已经存在相同的字符串,则返回常量池中的字符串引用;如果不存在,则在常量池中创建一个新的字符串,并返回这个新字符串的引用。

    String s1 = "Hello"; // 存储在字符串常量池
    String s2 = new String("Hello").intern(); // 使用 intern() 方法将新创建的字符串放入常量池
    System.out.println(s1 == s2); // 输出 true,因为 s1 和 s2 都指向常量池中的同一个 "Hello"
    
  • 性能考虑:字符串常量池可以减少内存使用,但过度使用 intern() 方法可能会导致性能问题,因为它需要在常量池中搜索或创建字符串。

String类方法


Java 中的 String 类是 java.lang 包的一部分,它用于表示和操作字符串。String 类是不可变的,这意味着一旦一个 String 对象被创建,它的内容就不能被改变。这个特性使得 String 对象在多线程环境中是线程安全的。

  1. 构造函数

    • String(): 创建一个空的字符串。
    • String(char data[]): 创建一个新的字符串,从字符数组 data
  2. 字符串比较

    • equals(Object another): 测试两个字符串是否相等。
    • equalsIgnoreCase(String another): 测试两个字符串是否相等,忽略大小写。
  3. 字符串长度

    • length(): 返回字符串的长度。
  4. 字符访问

    • charAt(int index): 返回指定索引处的字符。
  5. 字符串连接

    • concat(String str): 将指定字符串连接到此字符串的结尾。
  6. 子字符串

    • substring(int beginIndex): 返回一个新字符串,它是此字符串从 beginIndex 开始的子字符串。
    • substring(int beginIndex, int endIndex): 返回一个新字符串,它是此字符串从 beginIndexendIndex - 1 的子字符串。
  7. 字符串分割

    • split(String regex): 根据匹配给定正则表达式的模式来拆分此字符串。
  8. 大小写转换

    • toLowerCase(): 将字符串转换为小写。
    • toUpperCase(): 将字符串转换为大写。
  9. 字符串搜索

    • indexOf(int ch): 返回字符 ch 在此字符串中第一次出现处的索引。
    • indexOf(String str): 返回子字符串 str 在此字符串中第一次出现处的索引。
  10. 字符串替换

    • replace(char oldChar, char newChar): 返回一个新字符串,它是将此字符串中所有出现的 oldChar 替换为 newChar
  11. 字符串修剪

    • trim(): 返回字符串的副本,忽略前导空白和尾部空白。
  12. 字符串格式化

    • format(String format, Object... args): 将一个格式化字符串按照给定的格式和参数转换为新的字符串。

下面是一个使用 String 类的示例代码:

public class StringExample {
    public static void main(String[] args) {
        String greeting = "Hello, World!";
        System.out.println("Original String: " + greeting);

        // 字符串长度
        System.out.println("Length of String: " + greeting.length());

        // 访问特定位置的字符
        System.out.println("Character at index 7: " + greeting.charAt(7));

        // 子字符串
        String sub = greeting.substring(7, 12);
        System.out.println("Substring: " + sub);

        // 大小写转换
        String lowerCase = greeting.toLowerCase();
        String upperCase = greeting.toUpperCase();
        System.out.println("Lower Case: " + lowerCase);
        System.out.println("Upper Case: " + upperCase);

        // 字符串搜索
        int index = greeting.indexOf("World");
        System.out.println("Index of 'World': " + index);

        // 字符串替换
        String replaced = greeting.replace("World", "Java");
        System.out.println("Replaced String: " + replaced);

        // 字符串格式化
        String formatted = String.format("The value is: %d", 42);
        System.out.println(formatted);
    }
}

String 类提供了丰富的方法来处理字符串的各种操作,包括但不限于比较、搜索、替换、拆分和格式化。由于 String 的不可变性,每次对 String 进行修改操作时,实际上都会创建一个新的 String 对象。

正则表达式


正则表达式(Regular Expression,简称 Regex)是一种强大的文本处理工具,用于匹配字符串中的字符组合。它使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在编程语言和文本编辑器中,正则表达式通常用于搜索、替换、分割和验证文本。

基本组成:

  1. 字符:正则表达式中的普通字符(例如,abc)直接表示它自己。
  2. 特殊字符:有一些特殊字符具有特定的含义,如 . 表示任意单个字符,* 表示前面的元素可以出现零次或多次。
  3. 字符类[abc] 表示任何在括号内的字符(在这个例子中是 a、b 或 c)。
  4. 选择(x|y) 表示 x 或 y。
  5. 量词
    • *:零次或多次。
    • +:一次或多次。
    • ?:零次或一次。
    • {n}:恰好 n 次。
    • {n,}:至少 n 次。
    • {n,m}:从 n 到 m 次。

正则表达式示例:

  • .*:匹配任何内容。
  • ^hello:从字符串开始匹配 "hello"。
  • world$:匹配 "world" 结束的字符串。
  • [a-zA-Z]:匹配任何单个字母。
  • \d:匹配任何数字,等同于 [0-9]
  • \s:匹配任何空白字符(空格、制表符、换行符等)。
  • abc|xyz:匹配 "abc" 或 "xyz"。
  • a{3}:匹配三个连续的 "a"。
  • a{3,}:至少匹配三个 "a"。
  • a{3,5}:匹配 3 到 5 个 "a"。

正则表达式在编程中的应用:

在 Java 中,正则表达式是通过 java.util.regex 包中的类来实现的,主要包括:

  • Pattern:编译后的正则表达式,用于后续的匹配操作。
  • Matcher:用于执行正则表达式匹配操作的对象。

以下是一个简单的 Java 示例,演示如何使用正则表达式来检查字符串是否为有效的电子邮件地址:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExample {
    public static void main(String[] args) {
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@" +
                             "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";

        String email = "example@example.com";
        Pattern pattern = Pattern.compile(emailRegex);
        Matcher matcher = pattern.matcher(email);

        if (matcher.matches()) {
            System.out.println("这是一个有效的电子邮件地址。");
        } else {
            System.out.println("这不是一个有效的电子邮件地址。");
        }
    }
}

字符通配符

字符通配符通常在文件系统和编程语言中使用,用于匹配一个或多个字符。它们在不同的上下文中有不同的含义和用途

  1. 星号(*)
    • 在文件系统中,* 匹配任意数量的字符,包括零个字符。例如,*.txt 匹配所有扩展名为 .txt 的文件。
    • 在正则表达式中,* 是一个量词,表示前面的元素可以出现零次或多次。
  2. 问号(?)
    • 在文件系统中,? 匹配单个字符。例如,file?.txt 可以匹配 file1.txtfile2.txt 等,但不能匹配 file.txtfile12.txt
    • 在正则表达式中,? 也是一个量词,表示前面的元素可以出现零次或一次。
  3. 方括号([ ])
    • 在文件系统中,通常不使用方括号作为通配符。
    • 在正则表达式中,[ ] 定义了一个字符集,可以匹配方括号内的任意一个字符。例如,[abc] 可以匹配 'a'、'b' 或 'c'。
  4. 花括号({ })
    • 在文件系统中,花括号没有特殊含义。
    • 在正则表达式中,{n}{n,}{n,m} 用于指定量词的范围。例如,a{3} 表示 'a' 恰好出现三次,a{3,} 表示 'a' 至少出现三次,a{3,5} 表示 'a' 出现三到五次。
  5. 管道符号(|)
    • 在文件系统中,管道符号通常不作为通配符使用。
    • 在正则表达式中,| 表示选择,用来匹配两个或多个选项中的一个。例如,cat|dog 可以匹配 "cat" 或 "dog"。
  6. 点号(.)
    • 在文件系统中,点号通常用来表示文件扩展名的开始,如 file.
    • 在正则表达式中,. 表示任意单个字符(除了换行符)。
  7. 反斜杠(\)
    • 在文件系统中,反斜杠通常用来指定路径,如 C:\Users\Username
    • 在正则表达式中,反斜杠用作转义字符,用于转义那些具有特殊含义的字符,使其失去特殊含义,或者引入特殊字符。例如,\. 匹配一个点号,\d 匹配一个数字。

次数通配符

次数通配符用于指定正则表达式中模式出现的次数。以下是一些常见的次数通配符:

  1. *(星号)

    • 表示前面的元素可以出现零次或多次。例如,a* 可以匹配 "Bob"、"Alice",也可以匹配空字符串。
  2. +(加号)

    • 表示前面的元素至少出现一次或多次。例如,a+ 可以匹配 "apple" 中的 "ap",但不能匹配空字符串。
  3. ?(问号)

    • 表示前面的元素可以出现零次或一次。例如,a? 可以匹配 "Bob" 中的 "o",也可以匹配 "apple" 中的 "a" 或空字符串。
  4. {n}

    • 表示前面的元素恰好出现 n 次。例如,a{3} 可以匹配 "banana" 中的 "aaa"。
  5. {n,}

    • 表示前面的元素至少出现 n 次,可以出现无限次。例如,a{2,} 可以匹配 "aaaa" 中的 "aa","aaa","aaaaa" 等。
  6. {n,m}

    • 表示前面的元素至少出现 n 次,但不超过 m 次。例如,a{2,3} 可以匹配 "banana" 中的 "aa" 或 "aaa",但不能匹配 "a" 或 "aaaa"。
  7. *?(非贪婪匹配)

    • * 默认是贪婪的,它会尽可能多地匹配字符。使用 ? 可以使其变为非贪婪模式,尽可能少地匹配字符。例如,a*? 与 "aaaa" 匹配时,会匹配一个 "a" 而不是四个。
  8. +???

    • 类似于 *?+? 表示至少一次但尽可能少的匹配,?? 表示零次或一次但尽可能少的匹配。
  9. {n,m}?

    • 这表示非贪婪模式的 {n,m},匹配次数在 nm 次之间,但尽可能少。

其他通配符

除了次数通配符,正则表达式中还有一些其他的通配符,用于匹配特定的字符或模式:

  1. .(点)

    • 匹配除换行符之外的任何单个字符。
  2. ^(脱字符号)

    • 匹配输入字符串的开始位置。如果设置为多行模式,^ 匹配每一行的开始。
  3. $(美元符号)

    • 匹配输入字符串的结束位置。如果设置为多行模式,$ 匹配每一行的结束。
  4. |(管道符号)

    • 逻辑或操作符,用于匹配两个模式中的一个。例如,cat|dog 匹配 "cat" 或 "dog"。
  5. [](方括号)

    • 字符集,匹配方括号内的任意一个字符。例如,[abc] 匹配 "a"、"b" 或 "c"。
  6. [^...](否定字符集)

    • 匹配不在方括号内的任意字符。例如,[^abc] 匹配除了 "a"、"b"、"c" 之外的任何字符。
  7. \s

    • 匹配任何空白字符,包括空格、制表符、换行符等。
  8. \S

    • 匹配任何非空白字符。
  9. \d

    • 匹配任何数字,等同于 [0-9]
  10. \D

    • 匹配任何非数字字符。
  11. \w

    • 匹配任何字母数字字符,包括下划线。等同于 [a-zA-Z0-9_]
  12. \W

    • 匹配任何非字母数字字符。
  13. \b

    • 匹配一个单词边界,即单词和空格之间的位置。
  14. \B

    • 匹配非单词边界。
  15. (x)

    • 括号用于创建一个分组,捕获匹配的文本。括号中的内容可以被其他量词量化。
  16. (?:x)

    • 非捕获组,用于组织模式,但不捕获文本。
  17. (?=x)

    • 正向前瞻,匹配 x 前面的文本,但 x 不会成为匹配的一部分。
  18. (?!x)

    • 负向前瞻,匹配除了 x 前面的所有文本。
  19. (?<=x)

    • 正向后瞻,匹配 x 后面的文本,但 x 不会成为匹配的一部分。
  20. (?<!x)

    • 负向后瞻,匹配除了 x 后面的所有文本。
  21. \(反斜杠)**:

    • 转义特殊字符,使其失去特殊含义,或者表示特殊序列,如 \t(制表符)。
  22. \1\9

    • 反向引用,用于引用之前捕获的分组内容。
posted @ 2024-08-06 10:22  墨澜  阅读(3)  评论(0编辑  收藏  举报