杰瑞科技汇

Java char与String有何本质区别?

核心区别一句话总结

  • char单个字符,它是 Java 的基本数据类型(primitive type),表示一个 Unicode 字符,用单引号 表示。
  • String字符串,它是 Java 的一个类(class),表示一个字符序列(零个或多个字符),用双引号 表示。

char (字符)

char 是 Java 中用来表示单个字符的数据类型。

Java char与String有何本质区别?-图1
(图片来源网络,侵删)

a. 基本特性

  • 类型:基本数据类型
  • 大小:在 Java 中,char16 位(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 位整数,其范围是 065535 (Character.MIN_VALUECharacter.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 char与String有何本质区别?-图2
(图片来源网络,侵删)
  1. 安全性:字符串被广泛用于 Java 的许多地方,例如类名、文件名、网络连接地址等,如果字符串可变,这些关键信息就可能被恶意代码篡改,导致安全问题。
  2. 性能优化:由于字符串不可变,JVM 可以对其进行优化,最著名的就是字符串常量池,当你使用字面量 String s = "abc"; 创建字符串时,JVM 会在常量池中查找是否已经存在 "abc",如果存在,就直接返回引用,避免创建新对象,从而节省内存。
  3. 线程安全:不可变对象天生就是线程安全的,因为它们的状态不能被改变,多个线程可以同时访问一个 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

charString 的转换

它们之间经常需要相互转换。

a. Stringchar[] (字符数组)

使用 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. Stringchar

使用 charAt() 方法,注意,String 是字符的序列,所以不能直接转为单个 char,必须指定要获取哪个位置的字符。

String str = "world";
char ch = str.charAt(0); // ch = 'w'

d. charString

有几种简单的方法:

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

补充:StringBuilderStringBuffer

由于 String 的不可变性,在需要频繁修改字符串的场景下(例如循环拼接字符串),会创建大量临时的 String 对象,导致性能低下和内存浪费。

为了解决这个问题,Java 提供了 StringBuilderStringBuffer,它们是可变的字符序列。

  • 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

理解 charString 的区别,特别是 String 的不可变性,是掌握 Java 编程的基础。

分享:
扫描分享到社交APP
上一篇
下一篇