Scanner有意思的next读取

两个Scanner读取字符串问题

1. 问题由来

在使用两个Scanner对象的next去读取一行字符串中用空格分割的两个字符串时,发现输入完回车之后始终存在等待状态。只有再次输入字符串,再回车才可以继续执行。

  1. 问题还原

    代码

    public class Demo {
        public static void main(String[] args) {
            Scanner sc1 = new Scanner(System.in);
            Scanner sc2 = new Scanner(System.in);
            String name = sc1.next();
            String keyword = sc2.next();
            System.out.println("name:"+name);
            System.out.println("keyword:" + keyword);
        }
    }
    

    输入

    aaa bbb
    # ...一直按回车都没效果
    ccc	 # 直到输入ccc再次按回车才继续执行
    name:aaa
    keyword:ccc
    
  2. 问题解决

    模糊记得之前好像听说next会将输入读取到缓存中,那会不会是next把一行都读取了,只是按照空格将字符串分割存起来了呢?这样就会导致另外Scanner对象用next读取的时候,没有内容可读,导致一直阻塞下去。直到输入新内容。

  3. 验证

    要验证以上说法,只需再次调用第一个Scanner对象的next看是否输出第一行的第二个字符串即可。下面就是验证。

2. 验证假设

  1. 代码

    public class Demo {
        public static void main(String[] args) {
            Scanner sc1 = new Scanner(System.in);
            Scanner sc2 = new Scanner(System.in);
            String name = sc1.next();
            String keyword = sc2.next();
            System.out.println("name:"+name);
            System.out.println("keyword:" + keyword);
            System.out.println("sc1的第二次next:"+sc1.next());
        }
    }
    
  2. 结果

    aaa bbb
    ccc
    name:aaa
    keyword:ccc
    sc1的第二次next:bbb
    
  3. 结论

    Scanner的next方法每次会读取一行内容都本对象的缓冲区中,读取到的内容会按照空格分割成若干个元素,比如我们输入aaa bbb,sc1.next就把这一行都读取走了,然后根据空格把aaa和bbb分别存起来,并在aaa返回给name之后清楚了aaa,而bbb用于下一次调用next()时返回。

    也正因为是第一行的aaa bbb被sc1对象的next读取完了,当sc2对象的next来的时候发现没有内容,就阻塞等待,直到输入了ccc,sc2将ccc保存,赋值给keyword后清除。

    当sc1.next()再次调用的时候,sc1的bbb也被赋值了,清除。因此就会有上面的结果

3. 延伸

从上面中也可以推断,next在执行的时候,会判断缓冲区中是否有内容,如果有就直接返回而不去读取输入流的内容,如果没有则会读取一行用于分割缓存。


语文水平有限,说的可能不是很明白。不懂或者觉得存在不对的欢迎留言讨论。

你可能感兴趣的:(Java技术栈,java)