核心区别一句话总结
char:单个字符,它是 Java 的基本数据类型(primitive type),表示一个 Unicode 字符,用单引号 表示。String:字符串,它是 Java 的一个类(class),表示一个字符序列(零个或多个字符),用双引号 表示。
char (字符)
char 是 Java 中用来表示单个字符的数据类型。

a. 基本特性
- 类型:基本数据类型
- 大小:在 Java 中,
char是 16 位(2字节)的,这使其能够表示完整的 Unicode 字符集(包括中文、日文、emoji 等),而不仅仅是 ASCII 字符。 - 表示:使用单引号 。
- 默认值:
'\u0000'(即NUL字符)。
b. 如何声明和赋值
char ch1 = 'A'; // 存储一个大写字母 char ch2 = '中'; // 存储一个中文字符 char ch3 = '7'; // 存储一个数字字符 char ch4 = '\n'; // 存储一个换行符,这是转义字符 char ch5 = '\u4e2d'; // 使用 Unicode 转义序列,存储 '中' 字
c. char 的本质
在底层,char 本质上是一个无符号的 16 位整数,其范围是 0 到 65535 (Character.MIN_VALUE 到 Character.MAX_VALUE),你可以直接对 char 进行算术运算,因为它会使用其对应的 Unicode 码点值。
char ch = 'A'; System.out.println((int) ch); // 输出 65,因为 'A' 的 Unicode 码点是 65 char a = 'a'; char b = 'b'; System.out.println(b - a); // 输出 1,因为 'b' 的码点是 98,'a' 是 97 // 字母循环 char c = 'A'; c++; // c 变成了 'B' System.out.println(c); // 输出 B
d. char 相关的包装类
char 的包装类是 java.lang.Character,它提供了很多有用的静态方法来操作 char 类型,例如判断是否是字母、数字等。
char ch = '5';
System.out.println(Character.isDigit(ch)); // 输出 true
System.out.println(Character.isLetter(ch)); // 输出 false
System.out.println(Character.toUpperCase('a')); // 输出 'A'
String (字符串)
String 在 Java 中是一个对象,属于 java.lang 包,它用来表示一个或多个字符的序列。
a. 基本特性
- 类型:引用数据类型(对象)
- 不可变性:这是
String最核心、最重要的特性,一旦一个String对象被创建,它的内容就不能被改变,任何看起来修改String的操作(如concat,replace,substring)实际上都是创建了一个新的String对象,而原始对象保持不变。 - 表示:使用双引号 ,字符串字面量(
"hello")在 Java 中被视为String对象。 - 默认值:对于
String类型的成员变量,默认值是null。
b. 如何声明和赋值
String str1 = "Hello, World!"; // 使用字面量创建字符串
String str2 = new String("Java"); // 使用 new 关键字显式创建字符串对象
String str3 = ""; // 一个空字符串,长度为 0
String str4 = null; // 一个 null 引用,不指向任何字符串对象
c. String 的不可变性示例
String original = "hello";
System.out.println("原始字符串: " + original); // hello
// 调用 toUpperCase() 方法
String modified = original.toUpperCase();
System.out.println("修改后字符串: " + modified); // HELLO
System.out.println("原始字符串是否改变: " + original); // hello (仍然是 hello,没有改变)
为什么 String 要设计成不可变?

- 安全性:字符串被广泛用于 Java 的许多地方,例如类名、文件名、网络连接地址等,如果字符串可变,这些关键信息就可能被恶意代码篡改,导致安全问题。
- 性能优化:由于字符串不可变,JVM 可以对其进行优化,最著名的就是字符串常量池,当你使用字面量
String s = "abc";创建字符串时,JVM 会在常量池中查找是否已经存在"abc",如果存在,就直接返回引用,避免创建新对象,从而节省内存。 - 线程安全:不可变对象天生就是线程安全的,因为它们的状态不能被改变,多个线程可以同时访问一个
String对象而无需同步。
d. 常用方法
String 类提供了非常丰富的方法来操作字符串:
length(): 返回字符串长度。charAt(int index): 返回指定索引处的字符。substring(int beginIndex, int endIndex): 提取子字符串。concat(String str): 连接两个字符串(不推荐,推荐使用 或StringBuilder)。replace(char oldChar, char newChar): 替换字符。indexOf(String str): 查找子字符串首次出现的位置。split(String regex): 拆分字符串。toUpperCase(),toLowerCase(): 大小写转换。
String text = "Java is fun";
int len = text.length(); // len = 11
char firstChar = text.charAt(0); // 'J'
String sub = text.substring(5, 7); // "is"
boolean containsFun = text.contains("fun"); // true
char 与 String 的转换
它们之间经常需要相互转换。
a. String 转 char[] (字符数组)
使用 toCharArray() 方法。
String str = "hello"; char[] chars = str.toCharArray(); // chars = ['h', 'e', 'l', 'l', 'o']
b. char[] 转 String
使用 String 的构造方法。
char[] chars = {'J', 'a', 'v', 'a'};
String str1 = new String(chars); // str1 = "Java"
String str2 = String.valueOf(chars); // str2 = "Java"
c. String 转 char
使用 charAt() 方法,注意,String 是字符的序列,所以不能直接转为单个 char,必须指定要获取哪个位置的字符。
String str = "world"; char ch = str.charAt(0); // ch = 'w'
d. char 转 String
有几种简单的方法:
char ch = 'A'; // 方法1: 最简单直接的方式 String str1 = "" + ch; // str1 = "A" // 方法2: 使用 String.valueOf() String str2 = String.valueOf(ch); // str2 = "A" // 方法3: 使用 Character.toString() String str3 = Character.toString(ch); // str3 = "A"
char vs String 的选择
| 特性 | char |
String |
|---|---|---|
| 含义 | 单个字符 | 字符序列(零个或多个) |
| 类型 | 基本数据类型 | 引用类型(对象) |
| 不可变性 | 可变(其值可以改变) | 不可变不能改变) |
| 内存 | 占用固定 2 字节 | 内容可变,占用内存不固定 |
| 表示 | 'A' |
"A" |
| 主要用途 | 表示单个符号,如密码中的一个字符、状态码等。 | 表示文本,如人名、消息、文件内容、代码等。 |
如何选择?
- 如果你的数据永远只包含一个字符,比如处理单个输入、单个状态标记等,使用
char是合适的。 - 如果你的数据可能包含一个字符,也可能包含多个字符,或者你明确需要处理文本,那么始终使用
String,这是最常见的场景,用户的名字、一句话、一个文件路径等,都应该用String。
一个典型的错误:
// 错误:试图用 char 来存储多个字符 char password = "abc123"; // 编译错误!不兼容的类型: String 无法转换为 char
补充:StringBuilder 和 StringBuffer
由于 String 的不可变性,在需要频繁修改字符串的场景下(例如循环拼接字符串),会创建大量临时的 String 对象,导致性能低下和内存浪费。
为了解决这个问题,Java 提供了 StringBuilder 和 StringBuffer,它们是可变的字符序列。
StringBuilder: 线程不安全,但性能更高,在单线程环境下是首选。StringBuffer: 线程安全,但因为有同步开销,性能稍差。
// 低效的 String 拼接方式
String s = "";
for (int i = 0; i < 1000; i++) {
s = s + i; // 每次循环都创建一个新的 String 对象
}
// 高效的 StringBuilder 拼接方式
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // 在原有的对象上进行修改,不创建新对象
}
String result = sb.toString(); // 最后一次性转换为 String
| 特性 | char |
String |
|---|---|---|
| 本质 | 单个 16 位 Unicode 字符 | 不可变的字符序列对象 |
| 声明 | char c = 'A'; |
String s = "Hello"; |
| 核心特点 | 可变、基本类型 | 不可变、引用类型 |
| 适用场景 | 单个字符操作 | 几乎所有文本处理场景 |
| 性能考量 | 简单高效 | 频繁修改时性能差,应使用 StringBuilder |
理解 char 和 String 的区别,特别是 String 的不可变性,是掌握 Java 编程的基础。
