A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 #→_→ 于 2015-9-12 22:27 编辑

首先,最主观的代码是下面这样
Scanner sc=new Scanner(System.in);
         int m=sc.nextInt();
         String s = sc.nextLine();
         System.out.println(m);
         System.out.println(s);        
录入int之后,比如输入1,然后回车
输出的结果就只有1,然后换行空白
也就是说,nextLine()并没有录入数据
然后看API,
nextLint()的功能是,此扫描器执行当前行,并返回跳过的输入信息。
第一个疑问来了,跳过的信息,什么是跳过的信息
接着要继续看API
nextInt()的功能是,将输入信息的下一个标记扫描为一个 int。还有在API看到,默认是空白分隔符,所以下面测试可以用空格来输入多个int。

我个人理解,扫描器会连续的扫描输入,在没有数据的时候会阻塞,输入数据按回车之后会解除阻塞,nextInt()才能继续
验证这个想法,我测试了一下。
Scanner sc=new Scanner(System.in);
         int m=sc.nextInt();
         int m2=sc.nextInt();
          int m3=sc.nextInt();
         System.out.println("m="+m);
         System.out.println("m2="+m2);
         System.out.println("m3="+m3);
正常情况,输入1,回车。输入2,回车。输入3,回车。
这个在基础视频里经常见到的,这时候屏幕打印出
         m=1
         m2=2
         m3=3




然后换一个输入方式,键盘输入: 1 2 。回车之后,仍然在阻塞
不过再输入一个数字之后回车,屏幕就已经打印数据了,上面按了3次回车,这次只按了2次
         m=1
         m2=2
         m3=3



最后一次把3数字输完,键盘输入:1 2 3。回车,就直接打印了
         m=1
         m2=2
         m3=3


可以看出,它并没有马上完全读取,而是一个个的来,这个类似于迭代器,确实是,它继承了迭代器接口。
所以在输入1 2 的时候,Scanner对象里某个成员变量存的是 1 2 ,按了回车了后,int m = nextInt()迭代了一个int,然后按默认空白符为分隔的规则,跳过空白,程序往下走,int m2 = nextInt()又迭代了一个int,到int m3的时候,后面没数据了,然后程序停住了,回到了阻塞状态。到这的时候,猜测是不是按回车而释放的阻塞。然后简单测试了下,什么都不输入,无论按多少次回车,都仍然是阻塞状态,如果是按回车释放阻塞,而没有下一个迭代而仍然迭代是会出异常的,这没有出任何异常,纯粹的一直在阻塞,可以知道解除阻塞的不是按回车,可能只是回车促发某个方法,判断Scanner某个成员变量有没有内容。这个只是个人猜测。


下面到了测试nextLine()
而为什么nextInt()之后用不了nextLine(),最上面测试了,结果是直接是跳过了。
我就好奇,在Line()下面再加一个Line(),如下:
Scanner sc=new Scanner(System.in);
                 int m = sc.nextInt();
                 String s = sc.nextLine();
                 String s2 = sc.nextLine();
                 System.out.println("m="+m);
                 System.out.println("s="+s);
                 System.out.println("s2="+s2);

依次输入,1然后回车,2然后回车,3然后回车。结果输完2回车之后程序就结束了。结果如下:
                m=1
                s=
                s2=2

结果是,原本打算赋2给s的,结果赋值到了s2,s后面是空白。
想起API,nextLine()的功能是,此扫描器执行当前行,并返回跳过的输入信息。
个人猜测,Scanner的某个成员上仍然有数据被迭代!但是这数据是空白的,也不是空格,就像String可以有空白符,但却不是null。
继续测试,依次输入,1 2然后回车,3然后回车。结果出来了,看似正常
                 m=1
                 s= 2
                 s2=3

结果,s的值2前面有个空格,这是输入1之后加了个空格输入2。
返回跳过的信息,可能是上一个方法没有迭代完的信息,然后再测试一下。
依次输入,1 2 3 4 5然后回车,6回车。结果:
               m=1
               s= 2 3 4 5
               s2=6

确实是这样了,没有阻塞而是直接返回之前的信息,连空白符分隔的规则都直接跳过了。
但是问题来了,为什么新创建一次Scanner对象,直接调用nextLine()不会出现空白符。
估计这是int和line的阻塞方式不同,然后又测试一下,发现Line的阻塞直接和回车有关。
测试如下,依次输入 回车,回车,回车。然后程序结束了,输出如下:
                 s=
                s2=
                s3=

连空格都没有,空白字符串。可以知道,按回车直接释放阻塞,按一次读释放一次。

而倒过来,先输入nextLine()再输入nextInt()会没问题,很好理解,nextLine把之前的信息全部都迭代了,而剩下的空白字符,对于以空白字符为分隔的nextInt()是没有影响,再加没有内容无论怎么按回车都不会释放阻塞。

后来,直接打印scanner对象,发现一个变量



新建的Scanner打印出来是false,而使用过的Scanner打印出来的是true,
估计nextLine()是受这个变量影响,如果是false就先阻塞,如果是true就马上返回信息再阻塞,后面试了几次,好像这个变量只有新创建才是false,不过不知道我猜测的对不对,毕竟我只是个新手。。

不过貌似得出一个结论,不需要新创建一个Scanner,仅需要在使用前调用一次跳过之前的信息就可以了,不知道我这想法在实际开发能不能用。
也就是下面这样,
Scanner sc=new Scanner(System.in);
         int m=sc.nextInt();
         sc.nextLine();
         String s = sc.nextLine();
         System.out.println(m);
         System.out.println(s);     


实际等于刷新了迭代指针,不知这是否可行


3 个回复

倒序浏览
好详细, 得慢慢研究啊
回复 使用道具 举报
赞!!!!!!!!!
回复 使用道具 举报
forjunjian 发表于 2015-9-12 22:54
好详细, 得慢慢研究啊

我也不知道是不是这样,瞎猜的,但貌似这样也行,但是视频说需要重新创建一个scanner
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马