导读:本期聚焦于小伙伴创作的《Java Scanner的正确关闭时机:避免资源泄露与常见错误》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Java Scanner的正确关闭时机:避免资源泄露与常见错误》有用,将其分享出去将是对创作者最好的鼓励。

Java Scanner资源管理:何时关闭与最佳实践

在Java开发中,Scanner 是处理输入流的常用工具,尤其适合解析基本类型和字符串。但它作为一个实现了 AutoCloseable 接口的资源类,如果使用不当,很容易引发资源泄露或程序异常。很多开发者尤其是初学者,经常搞不清什么时候该关闭 Scanner,什么时候不应该关闭。本文将结合实际场景,详细讲解 Scanner 的资源管理规则与最佳实践。

Scanner的资源特性

Scanner 本身并不直接持有系统底层资源,它的资源特性取决于它所包装的输入流。当它包装的是需要手动释放的资源(比如文件流、网络连接流)时,关闭 Scanner 会连带关闭底层的输入流;如果包装的是标准输入流 System.in,关闭 Scanner 同样会关闭 System.in,而标准输入流一旦关闭,后续再想从控制台读取输入就会直接抛出异常。

不同场景下的关闭策略

场景1:包装文件、网络等需要释放的资源流

Scanner 用来读取文件、网络连接等需要手动释放的资源时,必须在操作完成后关闭 Scanner,否则会导致底层资源无法释放,造成资源泄露。这种情况下推荐使用 try-with-resources 语法,它会自动帮我们关闭资源,不需要手动调用 close() 方法。

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ScannerFileExample {
    public static void main(String[] args) {
        // try-with-resources 自动管理Scanner资源,操作完成后自动关闭
        try (Scanner scanner = new Scanner(new File("test.txt"))) {
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                System.out.println("读取到内容:" + line);
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + e.getMessage());
        }
        // try块结束后,scanner会自动调用close(),底层文件流也会被关闭
    }
}

场景2:包装标准输入流System.in

标准输入流 System.in 是JVM启动时创建的全局资源,不需要也不应该被随意关闭。如果创建了包装 System.inScanner 并调用了 close() 方法,System.in 会被一并关闭,后续再使用新的 Scanner 包装 System.in 读取输入时,就会抛出 IllegalStateException,提示流已经关闭。

因此,对于包装 System.inScanner,通常不建议主动关闭,除非你明确知道程序后续不会再使用标准输入流。

import java.util.Scanner;

public class ScannerSystemInExample {
    public static void main(String[] args) {
        // 包装标准输入流的Scanner,不建议主动关闭
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的名字:");
        String name = scanner.nextLine();
        System.out.println("你好," + name);
        
        // 错误示范:不要调用scanner.close(),否则System.in会被关闭
        // scanner.close(); 
        
        // 如果上面关闭了scanner,下面这行代码执行时会抛出异常
        // Scanner newScanner = new Scanner(System.in);
        // System.out.println("请再次输入:");
        // System.out.println(newScanner.nextLine());
    }
}

场景3:包装字符串、字节数组等内存中的数据源

如果 Scanner 包装的是字符串(new Scanner("字符串内容"))或者字节数组等内存中的数据源,这些数据源本身不涉及系统底层资源,因此关闭 Scanner 与否影响不大。不过为了代码规范,还是建议在不再使用时调用 close() 方法,或者同样使用 try-with-resources 管理。

import java.util.Scanner;

public class ScannerStringExample {
    public static void main(String[] args) {
        String content = "Java Scanner 资源管理示例";
        // 包装字符串的Scanner,关闭不影响其他资源,但建议规范关闭
        try (Scanner scanner = new Scanner(content)) {
            while (scanner.hasNext()) {
                System.out.println("读取到单词:" + scanner.next());
            }
        }
        // 自动关闭,无资源泄露风险
    }
}

最佳实践总结

  • Scanner 包装文件、网络等需要手动释放的底层资源时,优先使用 try-with-resources 语法,避免手动关闭遗漏。
  • 包装 System.inScanner 不要主动调用 close() 方法,除非确定程序后续不会再用到标准输入流。
  • 如果是在工具类或者长期运行的服务中创建包装 System.inScanner,建议将其作为单例使用,避免重复创建导致的不必要开销,同时也统一资源管理。
  • 不要在多个 Scanner 中包装同一个底层输入流,然后分别关闭,这样会导致第一个关闭的 Scanner 关闭底层流,后续其他 Scanner 无法使用。

常见错误示例与修正

下面是一个常见的错误案例:在读取完控制台输入后就关闭了 Scanner,导致后续输入失败。

import java.util.Scanner;

public class ScannerErrorExample {
    public static void main(String[] args) {
        Scanner scanner1 = new Scanner(System.in);
        System.out.println("请输入第一个数字:");
        int num1 = scanner1.nextInt();
        // 错误:关闭scanner1会连带关闭System.in
        scanner1.close();
        
        Scanner scanner2 = new Scanner(System.in);
        System.out.println("请输入第二个数字:");
        // 执行到这里会抛出异常,因为System.in已经被关闭
        int num2 = scanner2.nextInt(); 
        System.out.println("两个数字之和:" + (num1 + num2));
    }
}

修正后的代码:不主动关闭包装 System.inScanner,并且复用同一个 Scanner 实例。

import java.util.Scanner;

public class ScannerCorrectExample {
    public static void main(String[] args) {
        // 复用同一个Scanner实例,避免重复创建
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入第一个数字:");
        int num1 = scanner.nextInt();
        
        System.out.println("请输入第二个数字:");
        int num2 = scanner.nextInt();
        
        System.out.println("两个数字之和:" + (num1 + num2));
        // 程序结束前可以不关闭,或者如果确定不再使用,再关闭
        // scanner.close();
    }
}

Scanner资源管理关闭策略输入流最佳实践修改时间:2026-05-24 14:11:20

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。