charactercodingexception 是抽象受检异常,不能直接捕获;实际抛出的是其子类 malformedinputexception(输入字节非法)和 unmappablecharacterexception(字符不可映射),二者均继承自 ioexception,需显式处理。

CharacterCodingException 是 Java 中一个受检异常(checked exception),但它本身是抽象类,不能直接被抛出或捕获;实际抛出的是它的两个子类:MalformedInputException 和 UnmappableCharacterException。它们都继承自 IOException,因此必须显式捕获或声明抛出。
捕获 CharacterCodingException 的子类
由于 CharacterCodingException 是抽象的,你无法用 catch (CharacterCodingException e) 直接捕获——编译器会报错“无法实例化抽象类”。正确做法是捕获其具体子类,或更宽泛地捕获父类 IOException(推荐,因编解码异常通常发生在 I/O 流操作中):
- 捕获
MalformedInputException:输入字节序列不符合指定字符集编码规则(如 UTF-8 中出现非法字节) - 捕获
UnmappableCharacterException:输入字符在目标编码中无对应字节表示(如用 ISO-8859-1 编码中文字符) - 统一捕获
IOException:覆盖所有底层编解码失败场景,代码更简洁且符合常见实践
典型触发场景与捕获示例
这类异常常出现在 CharsetEncoder/CharsetDecoder、InputStreamReader、OutputStreamWriter 或 NIO 的 Charset.encode()/decode() 中。例如:
Charset utf8 = Charset.forName("UTF-8");
ByteBuffer bb = ...; // 包含非法 UTF-8 字节
try {
CharBuffer cb = utf8.decode(bb);
} catch (MalformedInputException e) {
System.err.println("输入字节格式错误:" + e.getMessage());
} catch (UnmappableCharacterException e) {
System.err.println("字符无法映射到目标编码:" + e.getMessage());
}
或者更常用的方式(推荐):
try (Reader reader = new InputStreamReader(inputStream, "UTF-8")) {
// 读取操作
} catch (IOException e) { // 包含所有编解码异常
// 统一处理
}
避免异常比捕获更重要
很多编解码异常其实可通过预检查或容错策略规避:
- 使用
Charset.isSupported("GBK")确认编码是否可用 - 对不确定来源的字节流,选用容错解码器:
Charset.forName("UTF-8").newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE) - 优先使用标准编码(UTF-8),减少跨平台兼容性问题
注意异常链与调试信息
这些异常通常包含关键上下文,比如出错位置(getInputLength()、getLength())、偏移量(getInputOffset())。打印日志时建议输出完整堆栈和异常详情,便于定位是源数据污染还是编码参数错误:
catch (IOException e) {
if (e instanceof MalformedInputException mie) {
System.err.printf("非法输入 @ offset %d, length %d%n",
mie.getInputOffset(), mie.getInputLength());
}
e.printStackTrace();
}Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











