在Main方法里产生随机单词, 导致异常BufferOverflowException
, 首先思考的是每次调用read()
方法应该会传入一个新的CharBuffer
吧(实际并不是, 后面说)
// Main.java
public static void main(String[] args) {
Scanner scanner = new Scanner(new RandomWords(100000));
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
}
// RandomWords.java
public class RandomWords implements Readable {
private static Random random = new Random(100);
private static final char[] CAPITALS =
"ABCDEFGHIGKLMNOPQRSTUVWXYZ".toCharArray();
private static final char[] LOWERS =
"abcdefghigklmnopqrstuvwxyz".toCharArray();
private int count;
public RandomWords(int count) {
this.count = count;
}
@Override
public int read(CharBuffer cb) throws IOException {
if(count-- == 0) {
return -1;
}
cb.append(CAPITALS[random.nextInt(CAPITALS.length)]);
int maxCount = 4;
for (int i = 0; i < maxCount; i++) {
cb.append(LOWERS[random.nextInt(LOWERS.length)]);
// System.out.println(cb.limit() + " - " + cb.position()); 下文指的注释代码
cb.append(CAPITALS[random.nextInt(CAPITALS.length)]);
}
cb.append(" ");
return 10;
}
}
来到报错位置, 这一段是CharBuffer源码里的部分, 发现是由于position >= limit导致的异常, 然后查找得到这两个值得获取方法position()和limit();
final int nextPutIndex() { // package-private
if (position >= limit)
throw new BufferOverflowException();
return position++;
}
在RandomWords.java代码加入 System.out.println(cb.limit() + " - " + cb.position());
位置见上文注释代码
经过打印发现
AyAvFkNuM
1024 - 1002
1024 - 1004
1024 - 1006
1024 - 1008
RcEsZqFwO
1024 - 1012
1024 - 1014
1024 - 1016
1024 - 1018
HxEsXaStX
1024 - 1022
1024 - 1024
position属性并没有随着每次调用read() 方法重置, 所以每次调用read()方法传入的是同一个 CharBuffer
. 回到Scanner源码
//Scanner.java
//通过查找找到调用read()方法的地方
private void readInput() {
if (buf.limit() == buf.capacity())
makeSpace();
// Prepare to receive data
int p = buf.position();
buf.position(buf.limit());
buf.limit(buf.capacity());
int n = 0;
try { // 这里调用了source.read() source就是构造方法传入的在RandomWords对象
n = source.read(buf);
} catch (IOException ioe) {
lastException = ioe;
n = -1;
}
if (n == -1) {
sourceClosed = true;
needInput = false;
}
if (n > 0)
needInput = false;
// Restore current position and limit for reading
buf.limit(buf.position());
buf.position(p);
}
发现其传入了buf
参数, 查找buf
来到
private Scanner(Readable source, Pattern pattern) {
assert source != null : "source should not be null";
assert pattern != null : "pattern should not be null";
this.source = source;
delimPattern = pattern;
buf = CharBuffer.allocate(BUFFER_SIZE);
buf.limit(0);
matcher = delimPattern.matcher(buf);
matcher.useTransparentBounds(true);
matcher.useAnchoringBounds(false);
useLocale(Locale.getDefault(Locale.Category.FORMAT));
}
发现是这个构造方法 对buf进行的赋值, 而 Scanner(Readable source)
这个构造方法也只是调用的上一个构造方法.
所以问题解决了, 由于我是在一开始就实例化了一个Scanner对象
. 导致传入read()
方法的buf
都是同一个 才导致的上文报错.