【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()方法接收,结果如图所示:

image

nextLine()方法接收,结果如图所示:

image

从上述输出结果差异可见,这两种方法的差异在于:

  • 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 类时,往往可能会发生一些出乎意料的结果。在使用时,应当注意:

  1. Scanner 对象所调用的 close() 方法只需要一句即可;

  2. 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);
        }
    }
    

    运行结果:

    image

    没有问题。但若将而这顺序调换一下:

    System.out.print("num = ");
    int num = scanner.nextInt();
    System.out.print("str = ");
    String str = scanner.nextLine();
    

    再编译运行:

    image

    nextLine() 的输入被跳过了。倘若逐句调试运行,可以发现,nextLine() 语句的确被调用了。

    以下引用自:使用Scanner类控制台输入时出现直接跳过输入过程问题_scanner 方法不继续往下走了_BUG担当的博客-CSDN博客

    这是因为二者扫描的原理不同。使用 nextLine() 时,读取的是字符串,输入内容后,nextLine() 方法开始读取内容,其读取方式是将回车符号(\r\n)一同读取出来,赋值时再将回车符除去;

    nextInt() 方法读取的是回车符前的内容,回车符还保留在缓冲区内。类似地,nextDouble()nextLong() 方法也有类似情况。因此,这就是在第二种情况中 nextLine() 方法似乎被跳过的原因。

    解决办法

    • nextInt()nextLine() 前,再插入一句 nextLine() ,将回车符读出来;
    • 使用 next() 方法代替 nextLine() 方法;
    • 都使用 nextLine() 方法读取字符串,赋值时使用类型转换(基本类型包装类,在进阶课程中有介绍);
  3. 当扫描器抛出异常 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.

  4. 扫描器抛出异常时,建议基于该引用变量重新新建对象,旧对象将会被视为垃圾被回收:

scanner = new Scanner(System.in);
posted @ 2021-07-18 23:34  Zebt  阅读(129)  评论(0)    收藏  举报