字符和字符串

字符与字符串

1. 字符类型(char)

char 是 Java 的 基本数据类型,用于表示单个字符,占 2 字节(16 bit),采用 Unicode 编码。

示例:

1
2
char c1 = 'A';
char c2 = '中';

Unicode 编码可通过将 char 赋值给 int 查看:

1
2
int n1 = 'A'; // 字母“A”的Unicodde编码是65
int n2 = '中'; // 汉字“中”的Unicode编码是20013

1.1 使用 Unicode 转义表示字符

格式:'\uXXXX'(十六进制)

1
2
3
// 注意是十六进制:
char c3 = '\u0041'; // 'A',因为十六进制0041 = 十进制65
char c4 = '\u4e2d'; // '中',因为十六进制4e2d = 十进制20013

2. 字符串类型(String)

char 不同,String引用类型。字符串使用双引号 "..." 包裹,可包含 0 个或多个字符。

1
2
3
4
String s = "";
String s1 = "A";
String s2 = "ABC";
String s3 = "中文 ABC";

3. 转义字符

因为字符串使用双引号"..."表示开始和结束,那如果字符串本身恰好包含一个"字符怎么表示?例如,"abc"xyz",编译器就无法判断中间的引号究竟是字符串的一部分还是表示字符串结束。这个时候,我们需要借助转义字符\

1
String s = "abc\"xyz"; // 包含7个字符: a, b, c, ", x, y, z

因为\是转义字符,所以,两个\\表示一个\字符:

1
String s = "abc\\xyz"; // 包含7个字符: a, b, c, \, x, y, z

常见转义字符

写法 含义
\" 双引号
\' 单引号
\\ 反斜杠
\n 换行
\r 回车
\t Tab
\u#### Unicode 字符

示例:

1
String s = "ABC\n\u4e2d\u6587"; // 包含6个字符: A, B, C, 换行符, 中, 文

4. 字符串连接(+)

Java 的 + 对字符串做了特殊处理,允许直接连接:

1
2
3
4
5
6
7
8
9
// 字符串连接
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "world";
String s = s1 + " " + s2 + "!";
System.out.println(s); // Hello world!
}
}

若连接非字符串,会自动转为字符串:

1
2
3
4
5
6
7
8
// 字符串连接
public class Main {
public static void main(String[] args) {
int age = 25;
String s = "age is " + age;
System.out.println(s); // age is 25
}
}

5. 多行字符串(Text Blocks,Java 13+)

使用 """ ... """

1
2
3
4
5
6
7
8
9
10
11
12
// 多行字符串
public class Main {
public static void main(String[] args) {
String s = """
SELECT * FROM
users
WHERE id > 100
ORDER BY name DESC
""";
System.out.println(s);
}
}

上述多行字符串实际上是5行,在最后一个DESC后面还有一个\n。如果我们不想在字符串末尾加一个\n,就需要这么写:

1
2
3
4
5
String s = """ 
SELECT * FROM
users
WHERE id > 100
ORDER BY name DESC""";

还需要注意到,多行字符串前面共同的空格会被去掉,即:

1
2
3
4
5
6
String s = """
...........SELECT * FROM
........... users
...........WHERE id > 100
...........ORDER BY name DESC
...........""";

.标注的空格都会被去掉。

如果多行字符串的排版不规则,那么,去掉的空格就会变成这样:

1
2
3
4
5
6
String s = """
......... SELECT * FROM
......... users
.........WHERE id > 100
......... ORDER BY name DESC
......... """;

即总是以最短的行首空格为基准。

特点:

  • 前后多余缩进会去掉
  • 默认包含末尾换行,如果不要,在结尾加 """ 前不留空格

6. 字符串的不可变性(Immutable)

字符串内容创建后不可修改。

示例代码:

1
2
3
4
5
6
7
8
9
// 字符串不可变
public class Main {
public static void main(String[] args) {
String s = "hello";
System.out.println(s); // 显示 hello
s = "world";
System.out.println(s); // 显示 world
}
}

解释:

  • "hello" 未变
  • 新创建 "world",变量 s 重新指向它
  • "hello" 依然存在,只是变量不再引用它

引用指向示例:

初始:

1
s"hello"

修改后:

1
2
s"world"
"hello" 依旧存在

观察执行结果,难道字符串s变了吗?其实变的不是字符串,而是变量s的“指向”。

执行String s = "hello";时,JVM虚拟机先创建字符串"hello",然后,把字符串变量s指向它:

1
2
3
4
5
6
      s


┌───┬───────────┬───┐
│ │ "hello" │ │
└───┴───────────┴───┘

紧接着,执行s = "world";时,JVM虚拟机先创建字符串"world",然后,把字符串变量s指向它:

1
2
3
4
5
6
      s ──────────────┐


┌───┬───────────┬───┬───────────┬───┐
│ │ "hello" │ │ "world" │ │
└───┴───────────┴───┴───────────┴───┘

原来的字符串"hello"还在,只是我们无法通过变量s访问它而已。因此,字符串的不可变是指字符串内容不可变。至于变量,可以一会指向字符串"hello",一会指向字符串"world"

考察引用:

1
2
3
4
5
6
7
8
9
// 字符串不可变
public class Main {
public static void main(String[] args) {
String s = "hello";
String t = s;
s = "world";
System.out.println(t); // t是"hello"还是"world"?
}
}

t 仍然指向 "hello"


7. 空值 null

引用类型变量可指向 null

1
2
3
String s1 = null; // s1是null
String s2 = s1; // s2也是null
String s3 = ""; // s3指向空字符串,不是null

区分:

含义
null 不指向任何对象
"" 空字符串,是一个长度为 0 的对象

8. 练习:将 Unicode 数字拼成字符串

题目:

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) {
// 请将下面一组int值视为字符的Unicode码,把它们拼成一个字符串:
int a = 72;
int b = 105;
int c = 65281;
// FIXME:
String s = a + b + c;
System.out.println(s);
}
}

正确答案(将 int 转为 char 再拼接):

1
2
String s = "" + (char) a + (char) b + (char) c;
System.out.println(s); // Hi!

9. 小结

  • char 是基本类型,表示一个 Unicode 字符,占 2 字节。
  • String 是引用类型,用于表示字符串。
  • 引用类型变量可以为 null,但空字符串 "" 不是 null
  • 字符串不可变:字符串内容不可修改,但变量可以改变指向。
  • 可用转义字符表示特殊字符。
  • 字符串支持 + 连接,也可使用 Java 13+ 的文本块。

字符和字符串
https://cryocore1225.github.io/java/j1/fca4c6bf.html
作者
Cryocore1225
更新于
2025年12月7日
许可协议