【Java流程笔记】2-1 Scanner 用户交互
§2-1 Scanner 用户交互
为了能够使用户与计算机进行交互,一种方法是使用Scanner
实现程序与人的交互,用于获取用户输入。java.util.Scanner
为 Java 5 的新特征,可以通过Scanner
类获取用户输入。
2-1.1 基本语法
语法:Scanner scanner = new Scanner(System.in);
通过Scanner
类的next()
与nextLine()
方法获取输入的字符串,在读取前我们一般需要使用hasNext()
与hasNextLine()
判断是否还有输入的数据。
另外,对于Scanner
这一类 IO 流的类,在使用完后需使用scanner.close();
将其关闭以节省资源。
下面对next()
与nextLine()
的区别做出介绍,输入同样的字符串Hello world
。
以下是代码(以next()
方法为例,含有判断语句):
import java.util.Scanner; //导入包
public class Demo01 {
public static void main(String[] args) {
//创建 Scanner 扫描器对象,用于获取键盘输入内容
Scanner scanner = new Scanner(System.in);
System.out.println("Please input data: ");
//判断是否还有输入内容
if (scanner.hasNext()) {
String str = scanner.next();
System.out.println("Output: "+str);
}
scanner.close();
}
}
以next()
方法接收,结果如图所示:
以nextLine()
方法接收,结果如图所示:
从上述输出结果差异可见,这两种方法的差异在于:
next()
:无法得到含有空格的字符串,有效字符后的空格视为分隔符或结束符;nextLine()
:以Enter
为结束符,可得到含有空格的字符串,返回回车前所有字符。
2-1.2 拓展用法
对于Scanner
类,可在 IDEA 上按住Ctrl
并单击Scanner
可查看其 Java 源码,这将有利于学习者发现更多其有关用法。现在通过一个简单的小情景拓展Scanner
的用法。
如何实现输入多个数字,并可在人工控制其输入是否结束的情况下,自动在结束输入时计算出所输入数字的和以及平均值?
欲解决此问题,则必须使用循环语句(while
),见下方代码:
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//创建变量:和与输入数字的个数
double sum = 0;
int n = 0;
System.out.println("请输入数据:");
while (scanner.hasNextDouble()) {
double d = scanner.nextDouble();
sum = sum + d;
n = n + 1;
System.out.println("你输入了第"+n+"数据,为"+d);
System.out.println("请输入数据,输入非数字以终止输入:");
}
System.out.println("总共输入数字"+n+"个,和为"+sum+",平均值为"+(double)(sum / n));
scanner.close();
}
}
用户所输入的内容可能为字符串,也可能为整型、浮点型等等,为防止出错,建议使用if (scanner.hasNextInt)
等先作判断后再接收输入。
2-1.3 注意事项
使用Scanner
类时,往往可能会发生一些出乎意料的结果。在使用时,应当注意:
-
Scanner
对象所调用的close()
方法只需要一句即可; -
nextLine()
和nextInt()
(nextDouble()
等)的扫描方式略有不同,二者在混用的时候可能会导致跳过输入的情况;例如:当
nextInt()
和nextLine()
混用时//先 nextLine() 再 nedxtInt() public class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("str = "); String str = scanner.nextLine(); System.out.print("num = "); int num = scanner.nextInt(); System.out.println("\n==================="); System.out.println("num = " + num); System.out.println("str = " + str); } }
运行结果:
没有问题。但若将而这顺序调换一下:
System.out.print("num = "); int num = scanner.nextInt(); System.out.print("str = "); String str = scanner.nextLine();
再编译运行:
nextLine()
的输入被跳过了。倘若逐句调试运行,可以发现,nextLine()
语句的确被调用了。以下引用自:使用Scanner类控制台输入时出现直接跳过输入过程问题_scanner 方法不继续往下走了_BUG担当的博客-CSDN博客
这是因为二者扫描的原理不同。使用
nextLine()
时,读取的是字符串,输入内容后,nextLine()
方法开始读取内容,其读取方式是将回车符号(\r\n
)一同读取出来,赋值时再将回车符除去;而
nextInt()
方法读取的是回车符前的内容,回车符还保留在缓冲区内。类似地,nextDouble()
,nextLong()
方法也有类似情况。因此,这就是在第二种情况中nextLine()
方法似乎被跳过的原因。解决办法:
- 在
nextInt()
后nextLine()
前,再插入一句nextLine()
,将回车符读出来; - 使用
next()
方法代替nextLine()
方法; - 都使用
nextLine()
方法读取字符串,赋值时使用类型转换(基本类型包装类,在进阶课程中有介绍);
- 在
-
当扫描器抛出异常
InputMismatchException
时,扫描器不会跳过(pass)导致该异常的令牌(token),因此需要通过其他方法检索或跳过它;原文:When a scanner throws an
InputMismatchException
, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method. -
扫描器抛出异常时,建议基于该引用变量重新新建对象,旧对象将会被视为垃圾被回收:
scanner = new Scanner(System.in);