关于Scanner调用 sc.nextInt() 异常try后不能二次输入导致死循环问题

先看下简化的代码,引出问题所在;

public class Run {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                System.out.println("1-登录    2-注册    3-查看用户    0-退出");
                int menu = sc.nextInt();
                if (menu == 0) {
                    System.out.println("感谢使用,再见!");
                    break;
                } else if (menu == 1) {
                    System.out.println("正在登录");
                } else if (menu == 2) {
                    System.out.println("正在注册");
                } else if (menu == 3) {
                    System.out.println("查看用户");
                }
            } catch (Exception e) {
                System.out.println("请重新输入");
            }
        }
    }
}

以上代码,输入字母将会无限死循环。

究其原因,是因为 scanner在要求用户输入的时候,其实是在内存中创建了一段用于用户输入,我们输入字母等就会存入该段内存。当我们用sc.nextInt()调用时,就不能调用出来,因为它不是我们要调用的int类型,这时就会报输入不匹配错误。我们用sc.nextInt()调用没把该段内存中的东西提出来,他就会一直占用这段内存,导致我们二次输入时,就不会再要求用户输入了,他会继续试图调用该段内存数值。明显地,每次都调用不出来,会报输入不匹配错误。

先看一种解决方法:

public class Run {
    public static void main(String[] args) {
        while (true) {
            try {
                System.out.println("1-登录    2-注册    3-查看用户    0-退出");
                int menu = new Scanner(System.in).nextInt();
                if (menu == 0) {
                    System.out.println("感谢使用,再见!");
                    break;
                } else if (menu == 1) {
                    System.out.println("正在登录");
                } else if (menu == 2) {
                    System.out.println("正在注册");
                } else if (menu == 3) {
                    System.out.println("查看用户");
                }
            } catch (Exception e) {
                System.out.println("请重新输入");
            }
        }
    }
}

这个解决方法,每次在调用用户输入方法时都会new 一个scanner对象,会占用我们的内存。所以效果其实并不好。

我们再看另一种解决方法:

就是我们清空该段用于用户输入的内存,或者把该段内存中的数值取出。所以我们在catch块中使用 sc.next(); 就可以解决。因为我们知道sc.next()是得到字符串所以可以把该段内存中的值取出。

public class Run {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                System.out.println("1-登录    2-注册    3-查看用户    0-退出");
                int menu = sc.nextInt();
                if (menu == 0) {
                    System.out.println("感谢使用,再见!");
                    break;
                } else if (menu == 1) {
                    System.out.println("正在登录");
                } else if (menu == 2) {
                    System.out.println("正在注册");
                } else if (menu == 3) {
                    System.out.println("查看用户");
                }
            } catch (Exception e) {
                sc.next();
                System.out.println("请重新输入");
            }
        }
    }
}

借鉴出处:https://blog.csdn.net/huan_mie/article/details/5949948

原文地址:https://www.cnblogs.com/xzh0717/p/11161278.html

时间: 2024-10-11 01:06:24

关于Scanner调用 sc.nextInt() 异常try后不能二次输入导致死循环问题的相关文章

调用contact某个联系人资料后返回数据到原来的Activity

package com.example.sample_5_10; import android.app.Activity; import android.app.Instrumentation.ActivityResult; import android.content.CursorLoader; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import androi

atitit.架构设计---方法调用结果使用异常还是返回值

atitit.架构设计---方法调用结果使用异常还是返回值 1. 应该返回BOOL类型还是异常 1 2. 最终会有四种状况,抛出异常.返回特殊值.阻塞.超时 1 3. 异常的优缺点点 1 4. java BlockingQueue的提示 2 5. 方案::两个都使用,一个api返回bool,一个throw 异常... 2 1. 应该返回BOOL类型还是异常 现在我遇到一个问题,我有一个函数,它要实现的功能是启动一个线程,然后让此线程监视一个事件. 但我应该返回BOOL类型还是异常哪? 作者:: 

解决Eclipse异常关闭后重启报 org.eclipse.swt.SWTException: Invalid thread access 的问题

. . . . . 很久没有写博客了,最近实在是太忙,一直想写点干货,但是一直没静下心来学习. 今天又在加班忙碌之中,结果谁知道越忙碌越出问题.先是 weblogic 没有正常启动,凭经验第一反应就是7001端口被其它程序占用了,然后通过命令查看之后,发现果然是被占用了,占用端口的竟然是Eclipse,查找占用端口的方式请移步至博主的另一篇文章<[windows]查询占用端口的程序——记一次解决webloigc启动失败的过程>. Eclipse之前是不占用7011端口的,这次占用估计可能是启动

调用Axis WebService异常:org.xml.sax.SAXException: Bad envelope tag: definitions

用Eclipse直接创建的webservice客户端,调用webservice: String endpoint = "XXXService?wsdl"; XXXServiceProxy proxy = new XXXServiceProxy(endpoint); try{ String result = proxy.request(); System.out.println(result); }catch(RemoteException e){ e.printStackTrace()

4.异常捕获后再次抛出

4.异常捕获后再次抛出 情况一:捕获后抛出原来的异常,希望保留最新的异常抛出点--fillStackTrace 情况二:捕获后抛出新的异常,希望抛出完整的异常链--initCause 1.捕获后重新抛出捕获的异常 在函数中捕获了异常,在catch模块中不做进一步的处理,而是向上一级进行传递 catch(Exception e){ throw e; } public class ReThrow { public static void f()throws Exception{ throw new

加载插件时,提示反射异常,调用的目标出现异常,该模块应包含一个程序集清单

加载插件时,提示反射异常,调用的目标出现异常,该模块应包含一个程序集清单.排查一晚上终于找到原因是因为引用第三方类库的版本不对,错误引用的版本需要另外的类库,但是开发的时候引用的类库版本是不需要的,导致向测试电脑拷贝程序时版本拷贝错误,引起跟开发机不一样的结果. 另外需注意: 千万不要向上面那么写,当第三方插件类库缺少东西时,会提示异常,不好排查,要把插件实例化的动作放在open方法里,这样会有更明确的提示 原文地址:https://www.cnblogs.com/xiaoxihebei/p/1

WIN取消100M隐藏分区、异常断电后绕过修复模式

1,安装win系统时取消100M的前置隐藏分区的办法: 安装系统时,进行到安装Windows界面时,不使用图形界面的新建(E)进行分区,直接按快捷键Shift+F10打开CMD命令行,输入以下命令进行分区: diskpart#进入diskpart模式,执行以下命令:list diskselect disk 0create partition primaryformat fs=ntfs quickexit 关闭CMD命令行窗口,点击刷新(R),就会看到磁盘 0已经格式化完成了,然后点击下一步(N)

中断与异常详解(二)

中断或异常发生之前 当 CPU 执行了当前指令之后,CS 和 EIP 这对寄存器中所包含的内容就是下一条将要执行 指令的逻辑地址.在对下一条指令执行前,CPU 先要判断在执行当前指令的过程中是否发生 了中断或异常. 如果发生了一个中断或异常 那么 CPU 将做以下事情 • 确定所发生中断或异常的向量i(在 0-255 之间). • 通过 IDTR 寄存器找到 IDT 表,读取 IDT 表第i项(或叫第i个门). • 分两步进行有效性检查:首先是“段”级检查,将 CPU 的当前特权级 CPL(存放

Magento中,调用静态块的几种方法[magento 二次开发]

在后台创建一个order_form静态块 Block Title :Order Form Identifier :order_form Status :Enabled Content :自定义内容 1.如果要在.phtml文件中直接调用这个静态块,那可以采用以下方法 [php] view plaincopy <?php $block = Mage::getModel('cms/block') ->setStoreId(Mage::app()->getStore()->getId()