一、核心对比速览
方法 | 功能 | 返回 true 的典型字符 |
用途 |
---|---|---|---|
Character.isISOControl(ch) |
是否为 ISO 控制字符 | \n , \t , \r , \b , \u007F |
过滤不可见控制符 |
Character.isDefined(ch) |
是否在 Unicode 中定义 | 'A' , '中' , 🙂 , \n , ' ' |
验证字符合法性 |
🔑 一句话总结:
isISOControl
:判断是不是“看不见的控制指令”isDefined
:判断是不是“Unicode 认可的合法字符”
二、Character.isISOControl()
详解
2.1 定义
public static boolean isISOControl(char ch)
public static boolean isISOControl(int codePoint)
- 判断字符是否属于 ISO/IEC 6429 标准定义的控制字符。
- 包括:
- C0 控制字符:
\u0000
到\u001F
(如\n=U+000A
,\t=U+0009
) - DEL:
\u007F
- C1 控制字符:
\u0080
到\u009F
(扩展控制字符)
- C0 控制字符:
✅ 常见控制字符:换行符
\n
、制表符\t
、回车\r
、退格\b
2.2 示例代码
System.out.println(Character.isISOControl('\n')); // true
System.out.println(Character.isISOControl('\t')); // true
System.out.println(Character.isISOControl('\r')); // true
System.out.println(Character.isISOControl(' ')); // false(空格不是控制字符)
System.out.println(Character.isISOControl('\u007F')); // true(DEL 删除符)
System.out.println(Character.isISOControl('A')); // false
System.out.println(Character.isISOControl('\u0085')); // true(C1: Next Line)
2.3 使用场景
- 清理日志或文本中的不可见控制字符
- 验证用户输入是否包含非法控制符
- 数据序列化前过滤控制字符
三、Character.isDefined()
详解
3.1 定义
public static boolean isDefined(char ch)
public static boolean isDefined(int codePoint)
- 判断字符是否在 Unicode 标准中被正式分配(defined)。
- 返回
true
如果:- 是字母、数字、标点、符号、控制字符、emoji 等任何 已分配的码位
- 返回
false
如果:- 是 未分配码位(如
\uFFFE
,\uFFFF
) - 是 代理对(Surrogates):
\uD800-\uDFFF
- 是 非字符(Non-characters):如
\uFDD0-\uFDEF
,\uFFFE
,\uFFFF
- 是 未分配码位(如
3.2 示例代码
System.out.println(Character.isDefined('A')); // true
System.out.println(Character.isDefined('中')); // true
System.out.println(Character.isDefined('🙂')); // true(emoji)
System.out.println(Character.isDefined('\n')); // true(控制字符也是定义的)
System.out.println(Character.isDefined('\u0000')); // true(NUL 是定义的)
System.out.println(Character.isDefined('\uFFFE')); // false(非字符)
System.out.println(Character.isDefined('\uFFFF')); // false(非字符)
System.out.println(Character.isDefined('\uE000')); // true(私用区,已定义)
3.3 使用场景
- 验证字符串是否包含非法 Unicode 码点
- 国际化文本处理中的字符校验
- 防止恶意输入使用未定义码位
四、关键区别与常见误区
✅ 正确认识:isISOControl()
vs isDefined()
字符 | isISOControl() |
isDefined() |
说明 |
---|---|---|---|
'A' |
false |
true |
普通字符 |
' ' (空格) |
false |
true |
空格不是控制字符 |
\t (制表符) |
true |
true |
控制字符也是定义字符 |
\n (换行) |
true |
true |
同上 |
\u007F (DEL) |
true |
true |
删除符 |
\uFFFE |
false |
false |
非字符,未定义 |
\uD800 |
true (部分) |
false |
代理对,未定义 |
🔁 重要关系:
所有isISOControl(ch)
为true
的字符,isDefined(ch)
也一定是true
但反过来不成立。
❌ 常见误区
误区 1:认为 isDefined()
可以判断“可见字符”
// 错误!
if (Character.isDefined(ch)) {
// 错误地认为 ch 是“可见字符”
// 实际上 '\n', '\t' 也是 defined
}
✅ 正确做法:使用
!Character.isISOControl(ch) && Character.isDefined(ch)
判断“合法可见字符”
误区 2:混淆 isISOControl()
与 isWhitespace()
System.out.println(Character.isWhitespace(' ')); // true
System.out.println(Character.isISOControl(' ')); // false
System.out.println(Character.isWhitespace('\t')); // true
System.out.println(Character.isISOControl('\t')); // true
✅
isWhitespace()
包括空格、Tab、换行等“空白字符”,而isISOControl()
更广。
五、最佳实践
✅ 实践 1:清理控制字符
public static String cleanControlChars(String str) {
if (str == null) return null;
return str.codePoints()
.filter(cp -> !Character.isISOControl(cp))
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
✅ 实践 2:验证输入合法性
public static boolean isValidText(String str) {
return str.codePoints().allMatch(Character::isDefined);
}
✅ 实践 3:安全处理用户输入
if (Character.isDefined(ch) && !Character.isISOControl(ch)) {
// 是合法 Unicode 字符,且不是控制字符 → 安全使用
buffer.append(ch);
}
六、总结:使用口诀
🔑 “isISOControl 查控制,isDefined 看定义,控制都 defined,defined 不都控”
✅ 核心要点回顾:
方法 | 用途 | 推荐场景 |
---|---|---|
isISOControl() |
过滤 \n , \t 等控制符 |
日志清洗、安全过滤 |
isDefined() |
验证字符是否合法 | 输入校验、国际化处理 |