杰瑞科技汇

java scanner 输入

目录

  1. 简介Scanner 是什么?
  2. 基本用法:如何读取基本数据类型(整数、小数、字符串等)。
  3. 进阶用法:读取一行、读取特定分隔符、判断是否有输入。
  4. 重要注意事项Scanner 的常见陷阱和最佳实践。
  5. 完整代码示例
  6. 关闭 Scanner
  7. 替代方案BufferedReader 简介

简介

Scanner 是 Java java.util 包中的一个类,它像一个“扫描仪”,可以解析原始类型和字符串的文本,默认情况下,它会从标准输入流(System.in)读取,也就是你的键盘。

核心思想Scanner 会将输入的文本分割成一个个“令牌”(token),然后你可以根据需要将这些令牌转换成不同的数据类型。


基本用法

要使用 Scanner,首先需要创建它的实例。

import java.util.Scanner; // 1. 导入 Scanner 类
public class ScannerDemo {
    public static void main(String[] args) {
        // 2. 创建一个 Scanner 对象,用于接收从键盘的输入
        Scanner scanner = new Scanner(System.in);
        // --- 读取不同类型的数据 ---
        // a) 读取一个整数
        System.out.print("请输入一个整数: ");
        int intValue = scanner.nextInt(); // 读取下一个整数类型的令牌
        System.out.println("你输入的整数是: " + intValue);
        // b) 读取一个小数 (浮点数)
        System.out.print("请输入一个小数: ");
        double doubleValue = scanner.nextDouble(); // 读取下一个 double 类型的令牌
        System.out.println("你输入的小数是: " + doubleValue);
        // c) 读取一个单词 (以空格为分隔符)
        System.out.print("请输入一个单词: ");
        String word = scanner.next(); // 读取下一个单词类型的令牌
        System.out.println("你输入的单词是: " + word);
        // d) 读取一行文本 (包括空格)
        System.out.print("请输入一行文本: ");
        scanner.nextLine(); // **重要!消耗掉 nextInt() 后留下的换行符**
        String line = scanner.nextLine(); // 读取一整行
        System.out.println("你输入的一行是: " + line);
        scanner.close(); // 3. 用完后关闭 Scanner
    }
}

执行流程示例

请输入一个整数: 100
你输入的整数是: 100
请输入一个小数: 3.14
你输入的小数是: 3.14
请输入一个单词: Hello
你输入的单词是: Hello
请输入一行文本: 你好,世界!
你输入的一行是: 你好,世界!

进阶用法

a) 读取一行 (nextLine())

next() 方法在遇到空格、Tab 或回车时会停止,而 nextLine() 会读取整行,直到遇到回车符。

b) 处理 next()nextLine() 之间的换行符问题 (非常重要!)

这是一个最常见的 Scanner 陷阱。

问题场景: 当你使用 nextInt(), nextDouble(), next() 等方法后,它们只会读取数字或单词,但不会消耗掉用户输入后按下的 回车键 (\n),这个回车符会留在输入缓冲区中。

如果你紧跟着调用 nextLine()nextLine() 会认为这个回车符是一个“空行”,并直接读取它,然后返回,导致你的程序跳过了用户输入的提示。

解决方案: 在调用 nextLine() 之前,如果前面使用了 nextInt() 等方法,先额外调用一次 scanner.nextLine() 来“消耗掉”那个多余的换行符。

// ... 代码接续上面的示例 ...
System.out.print("请输入你的年龄: ");
int age = scanner.nextInt();
System.out.println("年龄是: " + age);
// 如果这里直接写 scanner.nextLine(),它会读取上面按下的回车
// 所以我们需要先消耗掉它
scanner.nextLine(); // 关键代码!
System.out.print("请输入你的家庭住址: ");
String address = scanner.nextLine();
System.out.println("家庭住址是: " + address);

c) 判断是否有输入 (hasNextXXX())

有时候你不知道用户是否会输入,或者想检查下一个输入是否符合预期,这时可以使用 hasNextInt(), hasNextDouble(), hasNext() 等方法。

System.out.print("请输入一个整数(或直接回车退出): ");
if (scanner.hasNextInt()) {
    int num = scanner.nextInt();
    System.out.println("你输入的整数是: " + num);
} else {
    System.out.println("你没有输入有效的整数。");
}

重要注意事项和最佳实践

  1. 资源泄漏Scanner 是一个实现了 AutoCloseable 接口的类,它会占用系统资源(如文件句柄或输入流),如果长时间不关闭,可能会导致资源泄漏。

    • 最佳实践:使用 try-with-resources 语句,这样可以自动关闭 Scanner,即使发生异常也能保证资源被释放。
  2. 异常处理:如果用户输入了不符合要求的数据(在 nextInt() 时输入了 "abc"),程序会抛出 InputMismatchException,在实际应用中,你应该使用 try-catch 块来处理这种异常,防止程序崩溃。


完整代码示例 (结合最佳实践)

下面是一个更健壮、更完整的示例,它结合了 try-with-resources 和异常处理。

import java.util.InputMismatchException;
import java.util.Scanner;
public class RobustScannerExample {
    public static void main(String[] args) {
        // 使用 try-with-resources,自动关闭 Scanner
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println("--- 开始交互式输入 ---");
            // 读取整数
            while (true) {
                try {
                    System.out.print("请输入你的年龄 (整数): ");
                    int age = scanner.nextInt();
                    if (age > 0 && age < 150) {
                        System.out.println("年龄记录成功: " + age);
                        break; // 输入正确,退出循环
                    } else {
                        System.out.println("年龄输入不合理,请重新输入。");
                    }
                } catch (InputMismatchException e) {
                    System.out.println("输入错误:请输入一个有效的整数!");
                    scanner.next(); // 清除错误的输入,防止死循环
                }
            }
            // 消耗掉 nextInt() 留下的换行符
            scanner.nextLine();
            // 读取一行文本
            System.out.print("请输入你的名字: ");
            String name = scanner.nextLine();
            System.out.println("你好, " + name + "!");
            System.out.println("--- 输入结束 ---");
        } // scanner.close() 会在这里自动被调用
    }
}

关闭 Scanner

如上所述,Scanner 占用资源,应该被关闭。

// 方式一:手动关闭 (不推荐,容易忘记)
Scanner scanner = new Scanner(System.in);
// ... 使用 scanner ...
scanner.close(); // 必须记得调用
// 方式二:使用 try-with-resources (强烈推荐)
try (Scanner scanner = new Scanner(System.in)) {
    // ... 使用 scanner ...
} // 代码块执行完毕后,scanner.close() 会自动执行

注意:一旦关闭了 Scanner,它就不能再被使用了,再次调用其任何方法都会抛出 IllegalStateException


替代方案:BufferedReader

虽然 Scanner 非常方便,但在性能要求极高的场景下(处理大量数据输入),BufferedReader 通常比 Scanner 更快。

BufferedReader 的特点是:

  • 速度快:它有一个缓冲区,可以一次性读取大量数据,效率更高。
  • 功能相对单一:它只能读取字符串(readLine()),不像 Scanner 那样能直接解析成基本数据类型,如果需要转换,需要手动调用 Integer.parseInt(), Double.parseDouble() 等方法。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferedReaderExample {
    public static void main(String[] args) {
        // System.in 是字节流,BufferedReader 是字符流,需要用 InputStreamReader 转换
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
            System.out.print("请输入一行文本: ");
            String line = reader.readLine(); // 直接读取一行
            System.out.println("你输入的是: " + line);
            System.out.print("请输入一个整数: ");
            String numberStr = reader.readLine(); // 先读取为字符串
            try {
                int number = Integer.parseInt(numberStr); // 再手动转换
                System.out.println("你输入的整数是: " + number);
            } catch (NumberFormatException e) {
                System.out.println("输入的不是有效的整数。");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
特性 Scanner BufferedReader
易用性 ,可以直接解析 int, double 低,只能读字符串,需手动转换
性能 较慢 ,有缓冲区,适合大量数据
功能 丰富,可自定义分隔符 简单,主要就是读一行
适用场景 一般的控制台程序、交互式输入 性能敏感的输入场景、OJ刷题

给初学者的建议

  • 优先使用 Scanner,它简单、直观,能满足绝大多数日常开发需求。
  • 牢记 nextLine() 的陷阱,并学会用 scanner.nextLine() 来解决。
  • 养成使用 try-with-resources 的好习惯,确保资源被正确关闭。
  • 当你遇到性能瓶颈或者需要处理超大规模输入时,再考虑使用 BufferedReader
分享:
扫描分享到社交APP
上一篇
下一篇