Java String 字符串终极详解(全特性+全API+全示例)

一、String 基础定义与底层实现

1.1 核心定义

String 是 Java 中用于表示不可变字符序列的引用类型,位于 java.lang 包下。JVM 会自动加载该包,无需手动导入。它并非 8 种基本数据类型(byte、short、int、long、float、double、char、boolean),但经 JVM 特殊优化,拥有类似基本类型的使用体验,比如可直接赋值。

1.2 底层实现差异(JDK 8 vs JDK 9+)

String 的底层存储结构在 JDK 9 发生重大变更,核心目的是节省内存空间。具体差异如下:

| JDK版本 | 底层存储 | 优势 | 适用场景 |

| ---- | ---- | ---- | ---- |

| JDK 8及之前 | char[] value(每个char占2字节,UTF-16编码) | 实现简单,无需编码判断 | 包含大量非ASCII字符(如中文、特殊符号)的场景 |

| JDK 9及之后 | byte[] value + byte coder(coder标识编码:0=ISO-8859-1,1=UTF-16) | ASCII字符(占1字节)场景下节省50%内存 | 包含大量ASCII字符(如英文、数字、符号)的场景(绝大多数业务场景) |

示例验证:

    • 存储字符串 “abc”(全ASCII):JDK8 中 char[] 占 3×2=6 字节,JDK9 中 byte[] 占 3×1=3 字节,内存直接减半。
    • 存储 “中文123”(2个中文+3个ASCII):JDK8 占 5×2=10 字节,JDK9 中中文用 UTF-16(2字节/个)、ASCII 用1字节,总占 2×2 + 3×1=7 字节,仍节省内存。

二、String 不可变性(核心特性)

2.1 不可变性定义

String 对象一旦创建,其内部的字符序列(value数组)就无法被修改。所谓的“修改”操作(如拼接、替换),本质上都是创建新的 String 对象,原对象保持不变。

2.2 不可变性实现原理(JDK 8)

底层通过三大特性保障不可变性,缺一不可:

    1. private 修饰 value 数组:禁止外部直接访问 value,避免外部修改数组内容。
    1. final 修饰 value 数组:禁止 value 数组引用重新指向新的数组(但数组内部元素仍可通过反射修改,不推荐)。
    1. 无 set 方法:String 类未提供修改 value 数组元素的方法,所有操作均返回新对象。

2.3 不可变性的影响(优势+局限)

优势:

    • 线程安全:不可变对象天生线程安全,无需加锁,可在多线程环境下安全共享。
    • 支持字符串常量池:相同内容的字符串可复用常量池中的对象,节省内存(核心优化)。
    • 哈希值稳定:String 的 hashCode 基于 value 计算,一旦创建哈希值不变,适合作为 HashMap 等集合的键。

局限:

频繁修改字符串(如循环拼接)会创建大量临时对象,占用内存并增加 GC 压力,此时推荐使用 StringBuilder(非线程安全)或 StringBuffer(线程安全,效率较低)。

2.4 代码示例:不可变性验证

public class StringImmutabilityDemo {
public static void main(String[] args) {
String s1 = “abc”;
String s2 = s1; // s2 与 s1 指向常量池同一对象
s1 = s1 + “d”; // 拼接操作创建新对象 “abcd”,s1 指向新对象
System.out.println(s1); // 输出:abcd
System.out.println(s2); // 输出:abc(原对象未变)

// 反射破坏不可变性(仅作演示,禁止生产使用) try { Field valueField = String.class.getDeclaredField("value"); valueField.setAccessible(true); // 暴力访问私有字段 char[] value = (char[]) valueField.get(s2); value[0] = 'x'; System.out.println(s2); // 输出:xbc(原对象被修改) } catch (Exception e) { e.printStackTrace(); } }

}

三、字符串常量池(String Pool)

3.1 常量池定义与作用

字符串常量池是 JVM 为 String 专门设计的内存区域(属于方法区),用于存储字符串常量,核心作用是复用对象、减少内存占用。当创建字符串时,JVM 会先检查常量池:若存在相同内容的字符串,直接返回其引用;若不存在,创建新字符串存入常量池并返回引用。

3.2 字符串创建的两种方式对比

String 对象有两种创建方式,其在内存中的存储位置、是否复用常量池对象均不同,是面试高频考点。

方式1:字面量赋值(String s = “abc”)

优先使用常量池,流程如下:

    1. JVM 检查字符串常量池,是否存在 “abc”。
    1. 存在:直接将常量池中 “abc” 的引用赋值给 s。
    1. 不存在:在常量池创建 “abc” 对象,再将引用赋值给 s。

方式2:new 关键字创建(String s = new String(“abc”))

优先在堆内存创建对象,流程如下:

    1. 在堆内存中创建一个新的 String 对象。
    1. 检查字符串常量池,是否存在 “abc”。
    1. 不存在:在常量池创建 “abc” 对象,再让堆对象的 value 引用指向常量池对象。
    1. 存在:直接让堆对象的 value 引用指向常量池对象。
    1. 将堆对象的引用赋值给 s。

结论:new String(“abc”) 至少创建 1 个对象(堆对象),最多创建 2 个对象(堆对象+常量池对象,若常量池无对应值)。

3.3 代码示例:两种创建方式对比

public class StringPoolDemo {
public static void main(String[] args) {
// 方式1:字面量赋值,复用常量池对象
String s1 = “abc”;
String s2 = “abc”;
System.out.println(s1 == s2); // true(引用同一常量池对象)
System.out.println(s1.equals(s2)); // true(内容相同)

// 方式2:new 创建,堆对象不同 String s3 = new String("abc"); String s4 = new String("abc"); System.out.println(s3 == s4); // false(堆中两个不同对象) System.out.println(s3.equals(s4)); // true(内容相同) // 堆对象与常量池对象对比 System.out.println(s1 == s3); // false(分别指向常量池、堆) }

}

3.4 常量池相关方法:intern()

intern() 方法是 String 类提供的手动关联常量池的方法,作用是:将当前字符串对象的内容存入常量池(若不存在),并返回常量池中该对象的引用。

代码示例:intern() 使用

public class StringInternDemo {
public static void main(String[] args) {
String s1 = new String(“abc”);
String s2 = s1.intern(); // 将 “abc” 存入常量池(已存在),返回常量池引用
String s3 = “abc”;

System.out.println(s1 == s2); // false(s1指向堆,s2指向常量池) System.out.println(s2 == s3); // true(均指向常量池) // 常量池不存在时的场景 String s4 = new String("xy") + new String("z"); // 堆对象 "xyz",常量池无 "xyz" String s5 = s4.intern(); // 常量池创建 "xyz",返回其引用 String s6 = "xyz"; System.out.println(s4 == s5); // JDK7+ 为 true(常量池存储堆对象引用),JDK6 为 false System.out.println(s5 == s6); // true }

}

注意:JDK 7 对 intern() 做了优化,若常量池不存在该字符串,会直接存储堆对象的引用(而非复制内容),进一步节省内存。

四、String 核心 API 详解(附示例)

String 类提供了大量操作字符串的 API,按功能分类整理,结合示例说明核心用法,覆盖开发高频场景。

4.1 字符串长度与空判断

  • int length()

    返回字符串的长度(字符个数),注意与数组长度属性区分(数组用 length,字符串用 length() 方法)。// 示例:获取字符串长度

String str = “Java String”;
System.out.println(str.length()); // 输出:11(包含空格,空格算一个字符)

  • boolean isEmpty()

    判断字符串是否为空(长度为 0),仅当字符串是 "" 时返回 true,无法判断 null(判断 null 需先做非空校验,否则抛空指针异常)。// 示例:判断字符串是否为空

String emptyStr = “”;
String nonEmptyStr = “test”;
String nullStr = null;

System.out.println(emptyStr.isEmpty()); // 输出:true
System.out.println(nonEmptyStr.isEmpty()); // 输出:false
// System.out.println(nullStr.isEmpty()); // 报错:NullPointerException
// 安全判断写法
System.out.println(nullStr != null && !nullStr.isEmpty()); // 输出:false

4.2 字符串拼接与替换

4.2.1 拼接方法

  • String concat(String str)
    仅能拼接 String 类型,若传入 null 会抛出 NullPointerException,拼接后原字符串不变,返回新字符串。// 示例:使用 concat 拼接字符串

String str1 = “Hello”;
String str2 = “World”;
String result = str1.concat(" ").concat(str2); // 支持链式调用
System.out.println(result); // 输出:Hello World
System.out.println(str1); // 输出:Hello(原字符串未变)
// String error = str1.concat(null); // 报错:NullPointerException

  • + 号拼接
    支持任意数据类型(基本类型、引用类型)拼接,null 会被当作 "null" 处理,编译期优化为 StringBuilder(循环拼接除外,循环中 + 号会重复创建 StringBuilder,效率低)。// 示例:使用 + 号拼接字符串

String str = “年龄:”;
int age = 25;
String result1 = str + age; // 拼接基本类型
String result2 = “姓名:” + “张三” + “,” + result1; // 链式拼接字符串
String result3 = “null拼接:” + null; // 处理null

System.out.println(result1); // 输出:年龄:25
System.out.println(result2); // 输出:姓名:张三,年龄:25
System.out.println(result3); // 输出:null拼接:null

4.2.2 替换方法

  • String replace(char oldChar, char newChar)
    替换字符串中所有指定的旧字符为新字符,若旧字符不存在,返回原字符串。// 示例:替换指定字符

String str = “abacada”;
String result = str.replace(‘a’, ‘x’); // 替换所有 ‘a’ 为 ‘x’
String noChange = str.replace(‘z’, ‘y’); // 旧字符不存在,返回原字符串

System.out.println(result); // 输出:xbxcdxd
System.out.println(noChange); // 输出:abacada

  • String replace(CharSequence target, CharSequence replacement)替换字符串中所有指定的子串为目标子串,支持 String、StringBuilder 等 CharSequence 类型。// 示例:替换指定子串

String str = “Hello World, World is beautiful”;
String result = str.replace(“World”, “Java”); // 替换所有 “World” 为 “Java”

System.out.println(result); // 输出:Hello Java, Java is beautiful

  • String replaceAll(String regex, String replacement)

按正则表达式匹配内容,替换所有符合条件的子串,正则特殊字符需转义。// 示例:正则替换(去除所有数字、替换空格)
String str = “abc123def456 789”;
String noNum = str.replaceAll(“\d”, “”); // 匹配所有数字并替换为空
String noSpace = str.replaceAll(“\s”, “-”); // 匹配所有空格并替换为 “-”

System.out.println(noNum); // 输出:abcdef
System.out.println(noSpace); // 输出:abc123def456-789

  • String replaceFirst(String regex, String replacement)
    按正则表达式匹配内容,仅替换第一个符合条件的子串。// 示例:替换第一个匹配的子串

String str = “abacada”;
String result = str.replaceFirst(“a”, “x”); // 仅替换第一个 ‘a’ 为 ‘x’

System.out.println(result); // 输出:xbacada

4.3 字符串截取与分割

4.3.1 截取方法

  • String substring(int beginIndex)
    从指定索引(包含该索引字符)开始截取,到字符串末尾结束,索引越界会抛出 StringIndexOutOfBoundsException。// 示例:从指定索引截取到末尾

String str = “abcdefgh”;
String result1 = str.substring(3); // 从索引3开始截取
String result2 = str.substring(0); // 从开头截取,返回原字符串

System.out.println(result1); // 输出:defgh
System.out.println(result2); // 输出:abcdefgh
// String error = str.substring(10); // 报错:StringIndexOutOfBoundsException

  • String substring(int beginIndex, int endIndex)遵循“左闭右开”原则,截取从 beginIndex(包含)到 endIndex(不包含)的子串,beginIndex 不能大于 endIndex。// 示例:指定起始和结束索引截取

String str = “abcdefgh”;
String result = str.substring(2, 6); // 截取索引2、3、4、5的字符(不包含6)

System.out.println(result); // 输出:cdef
// String error = str.substring(6, 2); // 报错:StringIndexOutOfBoundsException

4.3.2 分割方法

  • String[] split(String regex)
    按正则表达式分割字符串,返回字符串数组,若末尾有匹配项,会忽略空字符串;若无匹配项,返回仅含原字符串的数组。// 示例:按正则分割字符串

import java.util.Arrays;

String str1 = “a,b,c,d,e”;
String[] arr1 = str1.split(“,”); // 按逗号分割
String str2 = “192.168.1.1”;
String[] arr2 = str2.split(“\.”); // 点是正则特殊字符,需双重转义
String str3 = “abc”;
String[] arr3 = str3.split(“,”); // 无匹配项,返回原字符串数组

System.out.println(Arrays.toString(arr1)); // 输出:[a, b, c, d, e]
System.out.println(Arrays.toString(arr2)); // 输出:[192, 168, 1, 1]
System.out.println(Arrays.toString(arr3)); // 输出:[abc]

  • String[] split(String regex, int limit)
    limit 控制分割结果的数组长度,limit>0 时,分割 limit-1 次,返回长度为 limit 的数组;limit=0 时,效果同 split(String regex);limit<0 时,分割所有匹配项,不忽略末尾空字符串。// 示例:指定limit分割字符串

import java.util.Arrays;

String str = “a,b,c,d,e”;
String[] arr1 = str.split(“,”, 3); // limit=3,分割2次,返回3个元素
String[] arr2 = str.split(“,”, 0); // 等同于无limit,忽略末尾空串
String[] arr3 = str.split(“,”, -2); // 分割所有,不忽略末尾空串(此处无空串)

System.out.println(Arrays.toString(arr1)); // 输出:[a, b, c,d,e]
System.out.println(Arrays.toString(arr2)); // 输出:[a, b, c, d, e]
System.out.println(Arrays.toString(arr3)); // 输出:[a, b, c, d, e]

4.4 字符串查找与判断

4.4.1 查找方法

  • int indexOf(int ch)
    返回指定字符(传入字符的 Unicode 编码也可)第一次出现的索引,未找到返回 -1。// 示例:查找字符第一次出现的索引

String str = “Hello World”;
int index1 = str.indexOf(‘o’); // 查找 ‘o’ 的索引
int index2 = str.indexOf(111); // 111是 ‘o’ 的Unicode编码,效果同上
int index3 = str.indexOf(‘z’); // 未找到,返回-1

System.out.println(index1); // 输出:4
System.out.println(index2); // 输出:4
System.out.println(index3); // 输出:-1

  • int indexOf(int ch, int fromIndex)
    从 fromIndex(包含)开始,查找指定字符第一次出现的索引,fromIndex 超出字符串长度返回 -1。// 示例:从指定索引开始查找字符

String str = “Hello World”;
int index = str.indexOf(‘o’, 5); // 从索引5开始查找 ‘o’

System.out.println(index); // 输出:7(索引5之后第一个 ‘o’ 在7的位置)

  • int indexOf(String str)
    返回指定子串第一次出现的索引,子串为空时返回 0,未找到返回 -1。// 示例:查找子串第一次出现的索引

String str = “Hello World Java”;
int index1 = str.indexOf(“World”); // 查找子串 “World”
int index2 = str.indexOf(“”); // 空串返回0
int index3 = str.indexOf(“Python”); // 未找到返回-1

System.out.println(index1); // 输出:6
System.out.println(index2); // 输出:0
System.out.println(index3); // 输出:-1

  • int lastIndexOf(int ch)
    返回指定字符最后一次出现的索引,未找到返回 -1,与 indexOf 方向相反。// 示例:查找字符最后一次出现的索引

String str = “abacada”;
int index = str.lastIndexOf(‘a’); // 查找最后一个 ‘a’

System.out.println(index); // 输出:6(字符串末尾的 ‘a’ 索引为6)

  • char charAt(int index)
    返回指定索引处的字符,索引范围为 0~length()-1,越界抛出 StringIndexOutOfBoundsException。// 示例:获取指定索引处的字符

String str = “Hello World”;
char c1 = str.charAt(3); // 获取索引3的字符
char c2 = str.charAt(str.length()-1); // 获取最后一个字符

System.out.println(c1); // 输出:l
System.out.println(c2); // 输出:d
// char error = str.charAt(20); // 报错:StringIndexOutOfBoundsException

4.4.2 判断方法

  • boolean equals(Object anObject)
    重写自 Object 类,严格比较字符串内容(区分大小写、字符顺序),仅当参数是 String 且内容完全一致时返回 true。// 示例:比较字符串内容(区分大小写)

String str1 = “Hello”;
String str2 = “Hello”;
String str3 = “hello”;
String str4 = new String(“Hello”);

System.out.println(str1.equals(str2)); // 输出:true(内容一致)
System.out.println(str1.equals(str3)); // 输出:false(大小写不同)
System.out.println(str1.equals(str4)); // 输出:true(内容一致,引用不同不影响)
System.out.println(str1.equals(null)); // 输出:false(避免空指针)

  • boolean equalsIgnoreCase(String anotherString)
    忽略大小写比较字符串内容,仅比较字符本身,不区分大小写(不改变原字符串大小写)。// 示例:忽略大小写比较内容

String str1 = “Java”;
String str2 = “java”;
String str3 = “JAVA”;

System.out.println(str1.equalsIgnoreCase(str2)); // 输出:true
System.out.println(str1.equalsIgnoreCase(str3)); // 输出:true
System.out.println(str1.equals(str2)); // 输出:false(对比equals方法)

  • boolean startsWith(String prefix)
    判断字符串是否以指定前缀开头,前缀为空串时返回 true。// 示例:判断是否以指定前缀开头

String str = “Hello World Java”;
boolean flag1 = str.startsWith(“Hello”); // 以 “Hello” 开头
boolean flag2 = str.startsWith(“World”); // 不以 “World” 开头
boolean flag3 = str.startsWith(“”); // 空前缀返回true

System.out.println(flag1); // 输出:true
System.out.println(flag2); // 输出:false
System.out.println(flag3); // 输出:true

  • boolean endsWith(String suffix)判断字符串是否以指定后缀结尾,后缀为空串时返回 true。// 示例:判断是否以指定后缀结尾

String str = “Hello World Java”;
boolean flag1 = str.endsWith(“Java”); // 以 “Java” 结尾
boolean flag2 = str.endsWith(“World”); // 不以 “World” 结尾

System.out.println(flag1); // 输出:true
System.out.println(flag2); // 输出:false

  • boolean contains(CharSequence s)判断字符串是否包含指定字符序列(子串),子串为空串时返回 true,本质是通过 indexOf 实现(indexOf != -1 则返回 true)。// 示例:判断是否包含指定子串

String str = “Hello World Java”;
boolean flag1 = str.contains(“World”); // 包含 “World”
boolean flag2 = str.contains(“Python”); // 不包含 “Python”

System.out.println(flag1); // 输出:true
System.out.println(flag2); // 输出:false

4.5 字符串转换(大小写、数组、基本类型)

4.5.1 大小写转换

  • String toLowerCase()
    将字符串中所有大写字母转换为小写字母,非字母字符保持不变,返回新字符串(原字符串不变)。// 示例:转换为小写字符串

String str = “Hello World 123!”;
String lowerStr = str.toLowerCase();

System.out.println(lowerStr); // 输出:hello world 123!
System.out.println(str); // 输出:Hello World 123!(原字符串不变)

  • String toUpperCase()
    将字符串中所有小写字母转换为大写字母,非字母字符保持不变,返回新字符串。// 示例:转换为大写字符串

String str = “Hello World 123!”;
String upperStr = str.toUpperCase();

System.out.println(upperStr); // 输出:HELLO WORLD 123!
System.out.println(str); // 输出:Hello World 123!(原字符串不变)

4.5.2 字符串与数组转换

  • char[] toCharArray()
    将字符串转换为字符数组,数组长度与字符串长度一致,字符顺序完全相同。// 示例:字符串转字符数组

import java.util.Arrays;

String str = “Hello”;
char[] charArr = str.toCharArray();

System.out.println(Arrays.toString(charArr)); // 输出:[H, e, l, l, o]
System.out.println(charArr[0]); // 输出:H(可通过数组索引访问字符)

  • static String valueOf(char[] data)
    静态方法,将字符数组转换为字符串,数组为 null 时返回 "null",而非抛出空指针。// 示例:字符数组转字符串

import java.util.Arrays;

char[] charArr1 = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’};
char[] charArr2 = null;
String str1 = String.valueOf(charArr1);
String str2 = String.valueOf(charArr2);

System.out.println(str1); // 输出:Hello
System.out.println(str2); // 输出:null(处理null安全)

4.5.3 字符串与基本类型转换

基本类型转 String:可通过 + 号拼接或 String.valueOf() 方法(推荐 valueOf(),效率更高、处理 null 更安全)。

String 转基本类型:通过对应包装类的 parseXxx() 方法(如 Integer.parseInt()),转换失败抛 NumberFormatException。

// 示例1:基本类型转字符串
int num = 123;
double d = 3.14;
boolean b = true;
// 方式1:valueOf(推荐)
String strNum = String.valueOf(num);
String strD = String.valueOf(d);
String strB = String.valueOf(b);
// 方式2:+ 号拼接
String strNum2 = num + “”;

System.out.println(strNum); // 输出:123
System.out.println(strD); // 输出:3.14
System.out.println(strB); // 输出:true
System.out.println(strNum2); // 输出:123

// 示例2:字符串转基本类型
String str1 = “456”;
String str2 = “3.1415”;
int num2 = Integer.parseInt(str1); // 字符串转int
double d2 = Double.parseDouble(str2); // 字符串转double

System.out.println(num2 + 100); // 输出:556
System.out.println(d2 + 0.8585); // 输出:4.0

// 转换失败示例(编译通过,运行报错)
// String strError = “abc”;
// int numError = Integer.parseInt(strError); // 报错:NumberFormatException

4.6 去除空格与比较

4.6.1 去除空格方法

    • String trim():去除字符串首尾的空白字符(空格、制表符 \t、换行符 \n 等),中间空格保留。
    • String strip():JDK 11+ 新增,功能与 trim() 类似,但支持 Unicode 空白字符(推荐使用)。

4.6.2 字符串比较(按字典序)

  • int compareTo(String anotherString)
    按字典序比较两个字符串,返回差值:
      • 返回 0:内容相同。
      • 返回正数:当前字符串大于目标字符串。
      • 返回负数:当前字符串小于目标字符串。
  • int compareToIgnoreCase(String str)按字典序比较,不区分大小写。

public class StringTrimCompareDemo {
public static void main(String[] args) {
// 去除空格
String s1 = " Hello World \t\n";
System.out.println(s1.trim()); // Hello World(去除首尾空白)
// System.out.println(s1.strip()); // JDK11+ 可用,效果同上,支持Unicode空白

// 字典序比较 String s2 = "abc"; String s3 = "abd"; String s4 = "ABC"; System.out.println(s2.compareTo(s3)); // -1(s2 < s3,差值为 'c'-'d'=-1) System.out.println(s3.compareTo(s2)); // 1(s3 > s2) System.out.println(s2.compareToIgnoreCase(s4)); // 0(不区分大小写,内容相同) }

}

五、String、StringBuilder、StringBuffer 对比

开发中频繁修改字符串时,需选择 StringBuilder 或 StringBuffer,三者核心差异集中在可变性、线程安全、效率上,对比如下:

| 特性 | String | StringBuilder | StringBuffer |

| ---- | ---- | ---- | ---- |

| 可变性 | 不可变(修改创建新对象) | 可变(直接修改底层数组) | 可变(直接修改底层数组) |

| 线程安全 | 安全(不可变) | 不安全(无同步锁) | 安全(方法加 synchronized 锁) |

| 效率 | 最低(频繁修改产生大量临时对象) | 最高(无锁 overhead) | 中等(锁机制消耗性能) |

| 底层实现 | char[](JDK8)/ byte[](JDK9+) | char[](JDK8)/ byte[](JDK9+) | char[](JDK8)/ byte[](JDK9+) |

| 适用场景 | 字符串不频繁修改(如常量、少量拼接) | 单线程环境,频繁修改字符串(如循环拼接) | 多线程环境,频繁修改字符串(如多线程日志拼接) |

5.1 代码示例:效率对比(循环拼接)

public class StringPerformanceDemo {
public static void main(String[] args) {
int loop = 100000; // 循环次数

// String 拼接(效率极低) long start1 = System.currentTimeMillis(); String s = ""; for (int i = 0; i < loop; i++) { s += i; } long end1 = System.currentTimeMillis(); System.out.println("String 耗时:" + (end1 - start1) + "ms"); // StringBuilder 拼接(效率最高) long start2 = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < loop; i++) { sb.append(i); } String result2 = sb.toString(); long end2 = System.currentTimeMillis(); System.out.println("StringBuilder 耗时:" + (end2 - start2) + "ms"); // StringBuffer 拼接(效率中等) long start3 = System.currentTimeMillis(); StringBuffer sbf = new StringBuffer(); for (int i = 0; i < loop; i++) { sbf.append(i); } String result3 = sbf.toString(); long end3 = System.currentTimeMillis(); System.out.println("StringBuffer 耗时:" + (end3 - start3) + "ms"); }

}

运行结果参考:String 耗时 5000+ms,StringBuilder 耗时 1-2ms,StringBuffer 耗时 5-10ms,差异显著。

六、常见面试题汇总

    1. String 为什么是不可变的?
      答:底层通过 private final char[] value(JDK8)+ 无修改方法实现,不可变性保障线程安全、支持常量池、哈希值稳定。
    1. String s = new String(“abc”) 创建了几个对象?
      答:至少 1 个(堆对象),最多 2 个(堆对象+常量池对象,若常量池无 “abc”)。
    1. String、StringBuilder、StringBuffer 的区别?
      答:核心差异在可变性、线程安全、效率(详见第五章对比表),单线程优先用 StringBuilder,多线程用 StringBuffer,不频繁修改用 String。
    1. intern() 方法的作用?JDK7 对其做了什么优化?
      答:将字符串内容存入常量池并返回常量池引用;JDK7 优化为:常量池不存在时,直接存储堆对象引用(而非复制内容),节省内存。
  1. 5.JDK8 与 JDK9+ 中 String 底层实现的差异?
    答:JDK8 用 char[](2字节/字符),JDK9+ 用 byte[] + coder(ASCII 占1字节,UTF-16占2字节),目的是节省内存。

    1. String 的 equals() 与 == 的区别?
      答:equals() 比较字符串内容(String 重写后),== 比较对象引用地址;基本类型用 == 比较值,引用类型默认 == 比较引用(除 String 常量池复用场景)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1178717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【人工智能学习-AI入试相关题目练习-第六次】

人工智能学习-AI入试相关题目练习-第六次1-前言3-问题题目训练第1問&#xff08;人工知能・探索アルゴリズム【相似】&#xff09;【選択肢】第2問&#xff08;人工知能・確率的推定【相似】&#xff09;【選択肢】第3問&#xff08;人工知能・強化学習【予測・模擬】&#xff…

微信小程序毕设项目推荐-基于SpringBoot+Vue的校园导航微信小程序的设计与实现基于springboot+微信小程序的校园导航与信息服务系统【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

氨糖软骨素那个牌子效果最好一 氨糖软骨素选购终极指南:2026高纯高浓新品测评全解析(附真实用户反馈+临床数据支撑) - 博客万

Meta描述:本文基于覆盖全国31省市4200名用户的真实体验与第三方检测数据,深度评测“氨糖软骨素那个牌子效果最好一”,从吸收技术、配方科学性到临床实证六大维度全面剖析,提供适配不同人群的理性选购方案。 摘要:面对市…

小程序毕设选题推荐:基于位置服务的城市路线分享系统基于springboot位置服务的城市路线分享系统小程序【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

小程序计算机毕设之基于springboot+微信小程序的校园导航与信息服务系统基于Java的校园导航微信小程序的设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

医学图像领域 顶刊顶会

医学影像领域的国际顶刊&#xff0c;尤其是被 中科院列为一区 Top 期刊 的&#xff0c; 主要包括以下几本。这些期刊在医学、工程、人工智能与影像交叉领域具有极高影响力&#xff0c;是科研人员冲击高水平成果的首选目标。 ✅ 中科院一区 Top 期刊&#xff08;医学影像方向&a…

除甲醛哪个牌子产品好?2026年全网畅销的十大除醛品牌揭晓,第一款效果惊艳 - 博客万

装修后残留的甲醛等有害气体,绝不是简单的"味道大"那么简单。它更像是一位潜伏在家中的"隐形杀手",在你还没察觉的时候,偷偷地侵蚀着家人的健康。短时间还好,要是长期生活在这样的环境里,它可…

【计算机毕业设计案例】基于微信小程序驾校预约练车平台的设计与实现基于springboot+微信小程序的驾考在线学习与测试系统(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

小程序计算机毕设之基于springboot+微信小程序的驾校在线学习考试小程序驾考在线学习与测试系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

2026年市面上专业的换热器供应商哪家好,高大空间空调机组/采暖机组/柜式空调机组/冷热水暖风机,换热器工厂推荐 - 品牌推荐师

行业洞察:换热器市场技术迭代与需求分化下的供应商选择 随着工业4.0与绿色建筑理念的深化,空调换热器市场正经历结构性变革。传统单一功能设备逐渐被集成化、定制化解决方案取代,工业厂房、商业综合体、农业种植等场…

如何解决节日礼物选购难题?2026 小众高级感礼物top10深度测评 - 博客万

小众送礼的核心诉求是 “不撞款、有品位、真实用”,但多数小众礼物要么是 “颜值大于实力” 的摆件,要么是功能冗余的网红款,很难兼顾质感与实用性。尤其在闺蜜互赠、情侣纪念、朋友生日等场景,既想送得独特,又怕…

小程序毕设项目:基于springboot+微信小程序的校园导航与信息服务系统(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【计算机毕业设计案例】基于SpringBoot+Vue校园导航微信小程序的设计与实现基于springboot+微信小程序的校园导航与信息服务系统(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

小程序毕设项目:基于springboot+微信小程序的驾考在线学习与测试系统(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【毕业设计】基于springboot+微信小程序的校园导航与信息服务系统(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

女性严重脱发用哪个牌子的洗发水?央视十大公认最好用的洗发水,首选天然植萃款 - 博客万

对于饱受脱发困扰的现代女性而言,选择洗发水不仅是日常清洁,更是一场关乎头皮生态重建的精准养护。当发际线逐渐后退、发缝日益明显,寻找一款真正有效的产品成为迫切需求。本文将结合专业测评与真实反馈,为您梳理十…

【win11禁止自动更新工具】Win11 25H2怎么永久关闭自动更新,彻底永久关闭Win11自动更新方法

win11系统老是自动更新怎么办&#xff1f;Win11 25H2怎么永久关闭自动更新&#xff1f;win11禁止自动更新工具有哪些&#xff1f;通常情况下一般建议用户会定期对电脑系统进行升级&#xff0c;以达安全防护的作用。但是经常开启win11自动更新也会带来一些问题&#xff0c;比如更…

2025干燥机评测:高复购率品牌优势在哪?沸腾干燥机/污泥干化/干燥设备/废液干燥系统/流化床干燥机,干燥机厂家排行榜 - 品牌推荐师

在化工、制药、食品等工业领域,干燥机作为核心工艺设备,直接影响产品品质、生产效率及环保合规性。面对行业对高效节能、智能环保设备的迫切需求,如何从众多品牌中筛选出技术领先、服务可靠、性价比突出的企业,成为…

Windows如何禁用设备连接提示音等通知声音?(静音外设提示) ,如何禁止windows自动更新

禁用U盘等设备连接提示音的方法有五种&#xff1a;一、设置中关闭自动播放总开关&#xff1b;二、控制面板重置自动播放并静音&#xff1b;三、禁用Shell Hardware Detection服务&#xff1b;四、清空注册表中DeviceConnect/DeviceDisconnect的默认值&#xff1b;五、声音方案设…

【课程设计/毕业设计】基于微信小程序的校园导航与信息服务系统基于springboot+微信小程序的校园导航与信息服务系统【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…