java 字符串

Java 字符串是用于表示文本数据的对象,核心实现类为 java.lang.String,其最关键特性是不可变性——对象创建后,字符序列无法被修改,任何看似“修改”的操作都会生成新的 String 对象。

一、核心特性

  1. 不可变性(Immutability)
    字符串创建后,其内部字符数组(char[],JDK 9+ 改为 byte[])的内容和长度无法修改。例如 str = str + "abc" 并非修改原对象,而是创建新的字符串对象并指向新地址。

    • 优势:线程安全、可缓存(如字符串常量池)、哈希值固定(利于作为 HashMap 键)。
    • 注意:频繁修改字符串(如循环拼接)会产生大量临时对象,建议用 StringBuilder(非线程安全)或 StringBuffer(线程安全)。
  2. 字符串常量池(String Constant Pool)
    JVM 为优化内存,在方法区维护一个“常量池”,存储字面量创建的字符串(如 "abc")。若创建相同字面量的字符串,会直接复用池中对象,而非新建。

    • 示例:
      String s1 = "abc"; // 先查常量池,无则创建并放入,s1指向池对象
      String s2 = "abc"; // 复用常量池对象,s1 == s2(地址相同)
      String s3 = new String("abc"); // 新建堆对象,s3指向堆,s3 != s1(地址不同)
      String s4 = s3.intern(); // 将堆对象的引用放入常量池,s4 == s1
      

二、字符串的创建方式

1. 字面量创建(推荐)

直接用双引号定义,优先使用常量池,内存更高效。

String str1 = "Hello Java"; // 字面量,存储于常量池
2. new 关键字创建

通过 new 实例化,会在堆内存创建对象(即使字面量已在常量池存在),再将对象地址赋值给变量。

String str2 = new String("Hello Java"); // 堆中新建对象,str2指向堆
String str3 = new String(new char[]{'H','e','l','l','o'}); // 通过字符数组创建

三、常用核心方法(重点)

String 类提供大量工具方法,以下为高频使用的核心方法:

方法分类方法示例功能说明
获取长度int length()返回字符串的字符个数(注意:中文、字母均算1个)。
判断内容boolean equals(Object obj)比较两个字符串的内容是否相等(区分大小写),需替代 ==== 比地址)。
boolean equalsIgnoreCase(String s)忽略大小写比较内容(如 "ABC".equalsIgnoreCase("abc")true)。
boolean contains(CharSequence s)判断当前字符串是否包含子串 s(如 "abcde".contains("bc")true)。
boolean startsWith(String prefix)判断是否以 prefix 开头(如 "http://a.com".startsWith("http")true)。
boolean endsWith(String suffix)判断是否以 suffix 结尾(如 "file.txt".endsWith(".txt")true)。
查找位置int indexOf(String s)从左开始查找子串 s 第一次出现的索引,未找到返回 -1(如 "abcabc".indexOf("ab")0)。
int lastIndexOf(String s)从右开始查找子串 s 第一次出现的索引,未找到返回 -1(如 "abcabc".lastIndexOf("ab")3)。
截取子串String substring(int beginIndex)beginIndex(含)开始截取到末尾(如 "abcde".substring(2) 返回 "cde")。
String substring(int begin, int end)begin(含)截取到 end(不含),注意 end <= length()(如 "abcde".substring(1,3) 返回 "bc")。
替换内容String replace(CharSequence old, CharSequence new)替换所有匹配的子串(如 "aaa".replace("a","b") 返回 "bbb")。
String replaceFirst(String regex, String replacement)仅替换第一个匹配的子串(支持正则,如 "aabbaa".replaceFirst("aa","xx") 返回 "xxbbaa")。
分割与合并String[] split(String regex)按正则 regex 分割字符串为数组(如 "a,b,c".split(",") 返回 {"a","b","c"})。
static String join(CharSequence delimiter, CharSequence... elements)delimiter 连接多个元素为字符串(如 String.join("-","2024","05","20") 返回 "2024-05-20")。
转换操作char[] toCharArray()将字符串转为字符数组(如 "abc".toCharArray() 返回 {'a','b','c'})。
String toLowerCase() / toUpperCase()转为全小写/全大写(如 "AbC".toLowerCase() 返回 "abc")。
String trim()去除字符串两端的空白字符(空格、制表符 \t、换行符 \n 等,中间空白保留,如 " a b ".trim() 返回 "a b")。
static String valueOf(Object obj)将任意类型(如 intObject)转为字符串(推荐,避免 null 转成 "null" 字符串)。

四、常见误区与注意事项

  1. ==equals() 的区别

    • ==:比较变量的内存地址(是否指向同一对象),仅字面量创建的相同字符串会返回 true
    • equals()String 重写了该方法,比较的是字符内容是否完全一致,是字符串比较的正确方式。
    • 错误示例:"abc" == new String("abc")false(地址不同);正确示例:"abc".equals(new String("abc"))true(内容相同)。
  2. 空字符串与 null 的区别

    • 空字符串(""):是一个有效对象,长度为 0,内存中存在(常量池或堆),可调用方法(如 "" .length() 返回 0)。
    • null:表示变量未指向任何对象,是“无地址”状态,直接调用方法会抛出 NullPointerException(空指针异常)。
    • 判空建议:先判 null 再判空字符串,如 if (str != null && !str.isEmpty())
  3. 字符串拼接的性能问题

    • + 拼接字符串(如 str += "a"),编译后会转为 StringBuilderappend() 方法,但循环中频繁拼接会重复创建 StringBuilder,性能差。
    • 优化方案:循环拼接时,手动创建 StringBuilder 对象,调用 append() 后用 toString() 收尾,示例:
      // 低效
      String s = "";
      for (int i = 0; i < 1000; i++) {
          s += i; // 每次循环新建 StringBuilder 和 String
      }
      // 高效
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < 1000; i++) {
          sb.append(i); // 仅操作一个 StringBuilder 对象
      }
      String result = sb.toString();
      

五、StringStringBuilderStringBuffer 对比

实际开发中需根据场景选择三者,核心区别如下:

类名可变性线程安全性能适用场景
String不可变安全(无修改操作)低(修改频繁时)存储固定文本、常量、哈希键等
StringBuilder可变不安全(无同步锁)单线程下频繁修改字符串(如循环拼接)
StringBuffer可变安全(方法加同步锁 synchronized中(锁开销)多线程下频繁修改字符串(如并发日志)

综上,String 是 Java 中最基础的文本类型,理解其不可变性常量池机制是核心,熟练掌握常用方法并根据场景选择 String/StringBuilder/StringBuffer,能有效提升代码效率和安全性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值