CharacterCodingException 是 Java NIO 中字符编解码错误的抽象基类,不能直接实例化,其具体子类 MalformedInputException 和 UnmappableCharacterException 才实际抛出。

Java 中没有 CharacterCodingException 这个类——它并不存在于标准 JDK API 中。你可能混淆了相关异常类型。
实际存在的核心编码异常是 CharacterCodingException 的父类
Java NIO 中真正用于字符编解码错误的基类是 java.nio.charset.CoderMalfunctionError(运行时错误,极少见),而实际抛出的、最常遇到的异常是:
-
java.nio.charset.MalformedInputException:输入字节序列不符合指定字符集的语法(如 UTF-8 中出现非法的 continuation byte) -
java.nio.charset.UnmappableCharacterException:字节序列可解析,但无法映射为该字符集中的有效字符(如用 ISO-8859-1 解码含中文的 UTF-8 字节) - 二者均继承自
java.nio.charset.CharacterCodingException——注意:这是个 抽象类,不能直接实例化,仅作异常分类顶层使用。
处理逻辑冲突的关键不在捕获抽象类,而在区分具体子类行为
所谓“逻辑冲突”,通常指:你期望某种容错策略(如跳过、替换、报错),但默认编解码器行为不符合预期。解决方式不是 catch CharacterCodingException,而是:
- 使用
CharsetEncoder/CharsetDecoder并显式设置 编码/解码策略(onMalformedInput()和onUnmappableCharacter()) - 避免依赖
String.getBytes(charset)或new String(bytes, charset)这类便捷方法——它们内部使用REPLACE策略且不暴露异常细节 - 例如,安全解码未知来源的字节数组:
Charset utf8 = StandardCharsets.UTF_8;
ByteBuffer bb = ByteBuffer.wrap(rawBytes);
CharsetDecoder decoder = utf8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT) // 遇到畸形输入就抛 MalformedInputException
.onUnmappableCharacter(CodingErrorAction.REPORT); // 遇到不可映射就抛 UnmappableCharacterException
try {
CharBuffer cb = decoder.decode(bb);
String result = cb.toString();
} catch (MalformedInputException e) {
// 处理 UTF-8 结构错误:截断、修复或记录
} catch (UnmappableCharacterException e) {
// 处理字节存在但无对应 Unicode 字符的情况(如某些旧 GBK 扩展字)
}
自定义字符集场景下需额外注意
若你实现了 CharsetProvider 或自定义 Charset,务必确保:
-
decodeLoop()和encodeLoop()方法在检测到非法输入时,正确调用coders.flush()前抛出对应的具体异常(而非笼统 throw new CharacterCodingException()) - 异常中应包含位置信息(如
getInputLength()、getPosition()),便于上层定位问题字节 - 不要在自定义编解码器中吞掉异常或静默替换——这会让“逻辑冲突”变得不可见
替代方案:用第三方库简化容错逻辑
对常见脏数据场景(如混合编码、BOM 混乱、截断 UTF-8),可考虑:
-
Apache Commons Text 的
CharSetUtils或UnicodeEscaper - juniversalchardet(自动编码检测)+ 显式 decode 控制
-
ICU4J 提供更细粒度的错误回调(
UConverter的U_FAILURE处理)
这些工具底层仍基于相同异常体系,但封装了常见恢复逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











