11String类型知识点

String类

1. String类的重要性

概念:Java专门提供的字符串类,符合面向对象思想(数据+操作封装在一起)

注意

  • C语言使用字符数组/指针+库函数操作字符串,是面向过程的

  • String在开发、笔试、面试中都非常重要


2. 常用方法

2.1 字符串构造

常用构造方式

复制代码
// 1. 使用常量串构造(最常用)
String s1 = "hello bit";

// 2. 使用new关键字
String s2 = new String("hello bit");

// 3. 使用字符数组构造
char[] array = {'h','e','l','l','o',' ','b','i','t'};
String s3 = new String(array);

注意易错点

  • String是引用类型,存储的是字符串的引用(地址)

  • ""引起来的也是String对象

  • 查看其他构造方法参考官方文档


2.2 String对象的比较

4种比较方式

1. ==比较引用地址
复制代码
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = s1;

System.out.println(s1 == s2);  // false,不同对象
System.out.println(s1 == s3);  // true,同一对象
2. equals()按字典序比较内容
复制代码
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("Hello");

System.out.println(s1.equals(s2));  // true
System.out.println(s1.equals(s3));  // false(大小写敏感)
3. compareTo()按字典序比较,返回int
复制代码
String s1 = "abc";
String s2 = "ac";
String s3 = "abcdef";

System.out.println(s1.compareTo(s2));  // -1,'b'<'c'
System.out.println(s1.compareTo(s3));  // -3,长度差
4. compareToIgnoreCase()忽略大小写比较
复制代码
String s1 = "abc";
String s2 = "ABC";
System.out.println(s1.compareToIgnoreCase(s2));  // 0

注意易错点

  • ==比较地址,equals比较内容

  • compareTo返回差值,可用于排序


2.3 字符串查找

常用查找方法

复制代码
String s = "aaabbbcccaaabbbccc";

System.out.println(s.charAt(3));           // 'b'
System.out.println(s.indexOf('c'));        // 6(第一次出现位置)
System.out.println(s.indexOf("bbb"));      // 3
System.out.println(s.indexOf('c', 10));    // 15(从指定位置开始找)
System.out.println(s.lastIndexOf('c'));    // 17(从后往前找)

注意易错点

  • indexOf找不到返回-1

  • charAt索引越界会抛出IndexOutOfBoundsException


2.4 字符串转化

1. 数值和字符串互转
复制代码
// 数字转字符串
String s1 = String.valueOf(1234);
String s2 = String.valueOf(12.34);

// 字符串转数字
int num1 = Integer.parseInt("1234");
double num2 = Double.parseDouble("12.34");
2. 大小写转换
复制代码
String s1 = "Hello";
System.out.println(s1.toUpperCase());  // "HELLO"
System.out.println(s1.toLowerCase());  // "hello"
3. 字符串与数组互转
复制代码
// 字符串转字符数组
String s = "hello";
char[] ch = s.toCharArray();

// 字符数组转字符串
char[] array = {'h','e','l','l','o'};
String s2 = new String(array);
4. 格式化
复制代码
String s = String.format("%d-%02d-%02d", 2023, 9, 5);
System.out.println(s);  // "2023-09-05"

注意易错点

  • parseInt/parseDouble可能抛出NumberFormatException

  • 格式化字符串语法类似C语言的printf


2.5 字符串替换

复制代码
String str = "helloworld";

System.out.println(str.replaceAll("l", "_"));     // "he__owor_d"
System.out.println(str.replaceFirst("l", "_"));   // "he_loworld"

注意易错点

  • String不可变,替换操作返回新字符串

  • replaceAll支持正则表达式


2.6 字符串拆分

复制代码
String str = "hello world hello bit";

// 按空格拆分
String[] result = str.split(" ");  
// ["hello", "world", "hello", "bit"]

// 限制拆分组数
String[] result2 = str.split(" ", 2);  
// ["hello", "world hello bit"]

// 特殊字符需要转义
String ip = "192.168.1.1";
String[] parts = ip.split("\\.");
// ["192", "168", "1", "1"]

注意易错点

  • .|*等特殊字符需要转义

  • \`需要写成\\`

  • 多分隔符用|连接:split(",|;")


2.7 字符串截取

复制代码
String str = "helloworld";

System.out.println(str.substring(5));      // "world"(从5到末尾)
System.out.println(str.substring(0, 5));   // "hello"([0,5)前闭后开)

注意易错点

  • 索引从0开始

  • 前闭后开区间:substring(begin, end)包含begin,不包含end


2.8 其他操作

复制代码
String str = "  hello world   ";

// 去除首尾空白
System.out.println("[" + str.trim() + "]");  // "[hello world]"

// 大小写转换(只影响字母)
System.out.println("Hello123".toLowerCase());  // "hello123"

3. 字符串的不可变性

概念:String对象一旦创建,内容不可更改

源码关键点

复制代码
public final class String {
    private final char value[];
}
  1. final class:不能被继承

  2. final char[]:value引用不能指向其他数组,但数组内容理论上可修改(实际被设计为不可修改)

代码示例

复制代码
String s = "hello";
s = s + " world";  // 创建了新对象,s指向新对象

为什么设计为不可变

  1. 便于实现字符串常量池

  2. 线程安全

  3. 缓存hash值,提高HashMap效率

注意易错点

  • 修改字符串会创建新对象,频繁修改效率低

  • final修饰引用类型:引用不能变,引用对象的内容可修改(但String内部做了限制)


4. 字符串修改的正确方式

错误方式(效率低)

复制代码
String s = "";
for (int i = 0; i < 10000; i++) {
    s += i;  // 每次循环创建新String对象
}

正确方式(使用StringBuilder/StringBuffer)

复制代码
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);  // 在原有对象上修改
}
String result = sb.toString();

5. StringBuilder和StringBuffer

5.1 常用方法

复制代码
StringBuilder sb = new StringBuilder("hello");

// 追加
sb.append(" world");      // "hello world"
sb.append(123);           // "hello world123"

// 插入
sb.insert(0, "Hi ");      // "Hi hello world123"

// 删除
sb.delete(0, 3);          // "hello world123"
sb.deleteCharAt(0);       // "ello world123"

// 替换
sb.replace(0, 4, "HELLO");  // "HELLO world123"

// 反转
sb.reverse();               // "321dlrow OLLEH"

// 转String
String str = sb.toString();

5.2 String vs StringBuilder vs StringBuffer

特性 String StringBuilder StringBuffer
可变性 不可变 可变 可变
线程安全 是(天然) 是(同步方法)
性能 修改时慢 稍慢(有同步开销)
使用场景 字符串常量 单线程字符串操作 多线程字符串操作

注意易错点

  • String和StringBuilder不能直接转换:

    • String→StringBuilder:构造方法或append()

    • StringBuilder→String:toString()

  • 单线程用StringBuilder,多线程用StringBuffer


6. 字符串常量池

概念:JVM为String开辟的特殊内存区域,避免重复创建相同字符串

复制代码
String s1 = "hello";              // 在常量池创建
String s2 = "hello";              // 直接引用常量池中的对象
String s3 = new String("hello");  // 在堆中创建新对象

System.out.println(s1 == s2);     // true(同一对象)
System.out.println(s1 == s3);     // false(不同对象)

intern()方法:将字符串放入常量池或返回已有引用

复制代码
String s4 = new String("world").intern();
String s5 = "world";
System.out.println(s4 == s5);  // true

注意易错点

  • ""直接赋值使用常量池

  • new String()在堆中创建新对象

  • 大量相同字符串时,常量池可节省内存


7. 常见OJ题示例

7.1 第一个只出现一次的字符

复制代码
public int firstUniqChar(String s) {
    int[] count = new int[256];
    for (char c : s.toCharArray()) {
        count[c]++;
    }
    for (int i = 0; i < s.length(); i++) {
        if (count[s.charAt(i)] == 1) {
            return i;
        }
    }
    return -1;
}

7.2 最后一个单词的长度

复制代码
public int lengthOfLastWord(String s) {
    s = s.trim();
    return s.length() - s.lastIndexOf(' ') - 1;
}

7.3 验证回文串

复制代码
public boolean isPalindrome(String s) {
    s = s.toLowerCase();
    int left = 0, right = s.length() - 1;
    while (left < right) {
        // 跳过非字母数字字符
        while (left < right && !Character.isLetterOrDigit(s.charAt(left))) left++;
        while (left < right && !Character.isLetterOrDigit(s.charAt(right))) right--;
        
        if (s.charAt(left) != s.charAt(right)) return false;
        left++;
        right--;
    }
    return true;
}

关键要点总结

  1. String不可变:修改操作返回新对象,原对象不变

  2. 比较字符串==比较地址,equals比较内容

  3. 效率问题:频繁修改用StringBuilder/StringBuffer

  4. 线程安全:单线程用StringBuilder,多线程用StringBuffer

  5. 常量池""直接赋值使用常量池,new String()在堆中创建

  6. 常用操作:查找、替换、拆分、截取、转换要熟练掌握

  7. 特殊字符:拆分时注意转义字符问题

相关推荐
索荣荣2 小时前
Java异步编程终极实战指南
java·开发语言
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 基于Java的图书馆座位预约管理系统设计为例,包含答辩的问题和答案
java·开发语言
qq_423233902 小时前
跨语言调用C++接口
开发语言·c++·算法
zhougl9962 小时前
Java Object.clone() 浅拷贝与深拷贝全解析
java·开发语言
飘若随风2 小时前
JS学习系列-01-什么是JS
开发语言·javascript·学习
余瑜鱼鱼鱼2 小时前
线程池总结
java·开发语言
定偶2 小时前
网络编程总结
开发语言·网络·数据结构·网络编程
w_t_y_y2 小时前
工具Cursor(三)MCP(3)常用的三方MCP Tools
java
claem2 小时前
Mac端 Python脚本创建与理解
开发语言·python·macos