核心区别(一句话总结)
char:单个字符,它是 Java 的基本数据类型,用单引号 表示。String:字符串,它是 Java 的一个类(位于java.lang包),表示一个字符序列,用双引号 表示。
char - 字符类型
char 是 Java 中唯一一个用于表示 Unicode 字符的类型。

1 基本特性
- 类型:基本数据类型 (Primitive Data Type)。
- 大小:在 Java 中,
char是 16 位(2 字节)无符号整数,因此可以表示 Unicode 字符集中的所有字符(从\u0000到\uffff)。 - 表示:使用单引号 括起来。
'A','1','中','\n'。 - 默认值:
'\u0000'(即NUL字符)。
2 如何声明和赋值
char ch1 = 'A'; // 一个英文字母 char ch2 = '中'; // 一个中文字符 char ch3 = '1'; // 一个数字字符 char ch4 = '\n'; // 一个转义字符(换行) char ch5 = '\u4e2d'; // 一个 Unicode 转义序列,代表 '中'
3 char 的本质
char 本质上是一个无符号的 16 位整数,你可以直接给它赋一个整数值,这个值会被当作 Unicode 码点来解析。
char ch6 = 65; // 65 是 'A' 的 Unicode 码点 System.out.println(ch6); // 输出 A char ch7 = '\u0041'; // \u0041 是 'A' 的十六进制 Unicode 码点 System.out.println(ch7); // 输出 A
4 常用操作
char 的操作通常是比较和算术运算(因为其本质是整数)。
char a = 'a';
char b = 'b';
// 比较字符
if (a < b) {
System.out.println("'a' 的 Unicode 码点小于 'b'"); // 输出
}
// 字符算术运算(基于其 Unicode 码点)
char nextChar = (char) (a + 1); // 'a' + 1 = 98, 即 'b'
System.out.println(nextChar); // 输出 b
String - 字符串类
String 在 Java 中是一个非常特殊的类,它被广泛使用并且有一些独特的性质。
1 基本特性
- 类型:引用数据类型 (Reference Data Type)。
- 本质:它是一个不可变的字符序列,这意味着一旦一个
String对象被创建,它的内容就不能被改变。 - 表示:使用双引号 括起来。
"Hello","你好", "123"`。 - 默认值:
null。
2 不可变性 的含义
这是 String 最重要的特性,当你看起来像是在修改一个字符串时,JVM 是在内存中创建了一个新的 String 对象,而原来的对象保持不变。

String s1 = "hello";
String s2 = s1; // s2 和 s1 引用同一个对象
// s1.concat(" world") 看起来像是修改了 s1
// 但实际上,它返回了一个新的 String 对象 "hello world"
// s1 本身并没有被改变
s1 = s1.concat(" world");
System.out.println(s1); // 输出 hello world
System.out.println(s2); // 输出 hello (s2 仍然指向原来的对象)
不可变性的好处:
- 线程安全不能被改变,所以在多线程环境下使用
String是安全的,无需额外的同步机制。 - 可以被安全地共享:可以放心地在多个地方传递同一个
String对象,不用担心它会被意外修改。 - 哈码缓存不变,
String对象的hashCode()值在创建后就不会改变,这使得String非常适合作为HashMap等哈希集合的键。
3 如何声明和创建
// 方式1:使用字面量(最常用)
// Java 会对字符串字面量进行“字符串池”(String Pool)优化
String str1 = "Hello, World!";
// 方式2:使用 new 关键字(不推荐,除非有特殊需求)
// 这会强制在堆上创建一个新的 String 对象,即使内容相同
String str2 = new String("Hello, World!");
4 String vs char[]
String 内部就是使用一个 char[] 数组来存储字符的。String 封装了这个数组,并提供了大量操作方法,使其功能更强大、更安全。
char[]是一个可变的字符数组。String是一个不可变的字符序列。
// char[] 的可变性
char[] chars = {'H', 'e', 'l', 'l', 'o'};
chars[0] = 'h'; // 合法,修改了第一个字符
System.out.println(chars); // 输出 [h, e, l, l, o]
// String 的不可变性
String str = "Hello";
// str[0] = 'h'; // 编译错误!String 没有 setCharAt() 方法
5 常用方法
String 类提供了非常丰富的方法来操作字符串。
String text = " Hello Java ";
// 获取长度
System.out.println(text.length()); // 输出 13
// 连接字符串
String newStr = text + " Programming"; // " Hello Java Programming"
// 转换大小写
System.out.println(text.toUpperCase()); // " HELLO JAVA "
System.out.println(text.toLowerCase()); // " hello java "
// 去除首尾空格
System.out.println(text.trim()); // "Hello Java"
// 获取子串
System.out.println(text.substring(2, 7)); // "Hello" (从索引2开始,到索引7之前)
// 查找字符或子串
System.out.println(text.indexOf('J')); // 输出 8
System.out.println(text.contains("Java")); // 输出 true
// 替换
System.out.println(text.replace("Java", "Python")); // " Hello Python "
// 分割
String[] parts = text.trim().split(" "); // ["Hello", "Java"]
for (String part : parts) {
System.out.println(part);
}
char 和 String 的关系与转换
它们之间可以相互转换。
1 char -> String
有多种方法可以将一个 char 转换为 String。
char ch = 'A';
// 方法1: 使用 String.valueOf()
String str1 = String.valueOf(ch);
// 方法2: 使用 构造函数
String str2 = new String(String.valueOf(ch)); // 或者 new String(new char[]{ch})
// 方法3: 使用 空字符串连接 (最简单)
String str3 = "" + ch;
System.out.println(str1); // A
System.out.println(str2); // A
System.out.println(str3); // A
2 String -> char
从一个 String 中获取 char。
String str = "Hello"; // 方法1: 使用 charAt(index) 获取指定位置的字符 char firstChar = str.charAt(0); // 'H' char secondChar = str.charAt(1); // 'e' // 注意:如果索引越界,charAt() 会抛出 StringIndexOutOfBoundsException // 方法2: 将 String 转换为 char[] 数组 char[] charArray = str.toCharArray(); // ['H', 'e', 'l', 'l', 'o'] System.out.println(charArray[0]); // H
StringBuilder 和 StringBuffer(性能补充)
由于 String 的不可变性,在需要频繁进行字符串拼接、修改的场景下(例如循环中拼接大量字符串),如果直接使用 或 concat(),会产生大量临时的 String 对象,严重影响性能。
这时就应该使用 StringBuilder 和 StringBuffer。
StringBuilder:可变的字符序列。非线程安全,但性能更高,在单线程环境下是首选。StringBuffer:可变的字符序列。线程安全(方法大多用synchronized修饰),但性能较低。
// 低效的方式(不推荐在循环中使用)
String result = "";
for (int i = 0; i < 1000; i++) {
result = result + i; // 每次循环都创建一个新的 String 对象
}
// 高效的方式(推荐)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // 在原有的对象上进行修改,不创建新对象
}
String efficientResult = sb.toString();
总结与对比
| 特性 | char |
String |
|---|---|---|
| 类型 | 基本数据类型 | 引用数据类型(java.lang.String 类) |
| 含义 | 表示单个 Unicode 字符 | 表示一个字符序列(字符串) |
| 不可变性 | 可变 | 不可变 |
| 内存 | 栈内存 | 堆内存(字符串池优化) |
| 表示 | 单引号 'A' |
双引号 "Hello" |
| 默认值 | '\u0000' |
null |
| 主要用途 | 存储单个字符,进行字符级别的操作 | 存储和处理文本,如句子、单词、文件路径等 |
| 性能 | 简单快速 | 频繁修改时性能差,应使用 StringBuilder |
| 关系 | String 内部由 char[] 实现 |
可以方便地与 char 相互转换 |
何时使用 char?
当你只需要处理一个独立的字符时,检查一个字符是否是数字、字母,或者进行字符的加密/解密等。
何时使用 String?
当你需要处理任何长度的文本时,存储用户名、文件内容、消息、SQL 语句等,这是绝大多数文本处理场景的选择。
