You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

疑问:通过JFrame设置System.in后Scanner无法读取输入,是操作有误还是不可行?

问题原因与解决方案

核心问题

你遇到的问题根源在于:Scanner实例在创建时就绑定了当前的System.in输入流。你的Main线程是在启动GUI后立刻创建了Scanner并开始读取,此时Scanner关联的是默认的控制台输入流;后续点击按钮通过System.setIn()替换System.in的指向,已经存在的Scanner并不会自动切换到新的输入流,所以始终读不到你设置的内容。

而System.out的打印操作正常,是因为每次调用System.out.println()等方法时,都会直接使用当前System.out的指向,所以替换后能立刻生效——这和Scanner的绑定逻辑完全不同。

解决方案

方案一:延迟创建Scanner,待输入流替换完成后再初始化

让主线程等待GUI按钮触发输入流替换的信号,之后再创建Scanner读取新的输入流:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.util.Scanner;

public class WriteToSystemIn extends JFrame {
    private static final Object LOCK = new Object();

    public WriteToSystemIn() {
        JButton button = new JButton("设置输入");
        button.addActionListener(e -> {
            ByteArrayInputStream bais = new ByteArrayInputStream("1\n".getBytes());
            System.setIn(bais);
            // 通知主线程可以读取
            synchronized (LOCK) {
                LOCK.notify();
            }
            dispose();
        });
        add(button);
        setSize(300, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(WriteToSystemIn::new);

        // 主线程等待输入流替换完成
        synchronized (LOCK) {
            try {
                LOCK.wait();
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
                return;
            }
        }

        // 此时System.in已被替换,创建Scanner读取
        Scanner scanner = new Scanner(System.in);
        if (scanner.hasNextLine()) {
            System.out.println("读取到的内容:" + scanner.nextLine());
        }
        scanner.close();
    }
}

方案二:直接使用自定义输入流创建Scanner(更推荐)

如果不需要全局替换System.in,只是想让Scanner读取指定内容,完全可以跳过修改System.in的步骤,直接给Scanner传入自定义的输入流,这种方式更灵活,也避免了全局替换可能带来的其他问题:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.util.Scanner;

public class WriteToSystemIn extends JFrame {
    public WriteToSystemIn() {
        JButton button = new JButton("读取自定义输入");
        button.addActionListener(e -> {
            ByteArrayInputStream bais = new ByteArrayInputStream("1\n".getBytes());
            Scanner scanner = new Scanner(bais);
            if (scanner.hasNextLine()) {
                System.out.println("读取到的内容:" + scanner.nextLine());
            }
            scanner.close();
        });
        add(button);
        setSize(300, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(WriteToSystemIn::new);
    }
}

内容的提问来源于stack exchange,提问作者Jun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:45:47