Readable 是 Java 中定义 read(CharBuffer) 方法的轻量级字符读取接口,Scanner 通过它统一获取可扫描的字符流;其实现需处理 EOF(返回-1)、批量填充 CharBuffer,并不管理资源或支持回退。

Readable 接口本身不直接“为 Scanner 提供变量源”,而是为 Scanner 提供一种统一的字符数据读取能力。Scanner 的构造函数支持 Readable 类型参数,意味着只要一个类实现了 read(CharBuffer) 方法,它就能作为 Scanner 的输入源——但这不是为了“提供变量”,而是提供**可扫描的字符流**。
Readable 是什么:轻量级字符读取契约
Readable 是 Java 中一个函数式接口,只定义了一个方法:
-
int read(CharBuffer cb):尝试将字符写入给定的CharBuffer,返回实际写入的字符数;返回 -1 表示已到达流末尾(EOF)。 - 它不管理资源(如打开/关闭)、不支持跳过或标记、也不保证阻塞行为——这些都由实现类自行决定。
- 常见实现包括
Reader子类(如StringReader、FileReader)、InputStream的适配器(InputStreamReader),以及自定义逻辑。
Scanner 如何使用 Readable 实例
Scanner 在构造时接收 Readable,并在内部循环调用其 read(CharBuffer) 方法来填充缓冲区,进而按分隔符切分 token。关键点:
- Scanner 不关心 Readable 背后是字符串、文件、网络流还是内存生成的数据——只要能填满 CharBuffer 就行。
- Scanner 自动处理编码(若 Readable 基于 Reader)、缓冲、分隔符匹配和类型转换(如 nextInt())。
- 注意:Scanner 不会自动关闭 Readable,需手动管理(除非使用 try-with-resources 且 Readable 同时实现了
AutoCloseable)。
手写 Readable 实现:以动态字符串生成为例
假设你想让 Scanner 扫描一组运行时拼接的字符串(比如模拟配置行),可这样实现:
class DynamicSource implements Readable {
private final Iterator<String> lines;
private String current = null;
DynamicSource(Iterable<String> data) {
this.lines = data.iterator();
}
@Override
public int read(CharBuffer cb) {
if (current == null && lines.hasNext()) {
current = lines.next() + "\n"; // 模拟带换行的输入行
}
if (current == null) return -1; // EOF
int len = Math.min(current.length(), cb.remaining());
if (len == 0) return 0;
cb.put(current, 0, len);
current = current.substring(len);
if (current.isEmpty()) current = null;
return len;
}
}
然后传给 Scanner:
Scanner sc = new Scanner(new DynamicSource(List.of("42", "hello", "3.14")))- 后续调用
sc.nextInt()、sc.next()、sc.nextDouble()即可按需解析。
常见误区与注意事项
- Readable ≠ 可重读:read() 通常是一次性消费,不可回退。Scanner 内部也不支持“un-read”;若需重复扫描,请重新创建 Scanner 或使用支持 mark/reset 的 Reader。
- CharBuffer 大小影响性能:Scanner 默认使用 1024 字节缓冲区。若你的 read() 每次只写入 1 字符,效率极低;应尽量批量填充。
-
异常处理在实现中:read() 声明抛出
IOException,你的实现必须合理传播或封装 I/O 异常(如文件读取失败、网络中断)。 -
别混淆 Readable 和 Readable 的包装类:例如
Files.newBufferedReader()返回的是BufferedReader(继承 Reader,也实现 Readable),但直接 new StringReader(...) 更轻量。

















