Java Scanner输入触发InputMismatchException及类层级声明问题咨询
异常原因分析
首先澄清认知误区:将String类型成员变量声明在类层级完全不会导致该异常,Java的成员变量声明位置和Scanner输入处理逻辑无任何关联,你遇到的问题完全来自输入流处理的逻辑错误。
1. 多Scanner实例绑定同一输入流的缓冲区隔离问题
你在SugarSmashPlayer类中定义了Scanner in = new Scanner(System.in),每个类实例(包括子类PremiumSugarSmashPlayer的实例)都会创建独立的Scanner对象,所有Scanner都包装同一个标准输入流System.in。
- 不同Scanner实例的输入缓冲区互相隔离
- 控制台输入的内容会被先创建的Scanner缓冲区截获,后创建的Scanner无法读取到完整的输入内容,甚至会读到残留的空内容、换行符,当尝试将其解析为int类型时,就会触发
InputMismatchException。
2. nextInt()的换行符残留导致输入序列错位
nextInt()方法仅读取输入缓冲区中的数字内容,不会吞掉数字后方的换行符(\n)。你紧接着调用name = in.nextLine(),会直接把这个残留的换行符作为一行读取,得到空字符串。
该问题本身不会直接抛错,但会彻底打乱后续的输入读取顺序:
举个实际场景的输入流处理示例,假设你按如下顺序输入:
100 # 按回车,对应id的输入 张三 # 按回车,对应name的输入 150 # 按回车,对应数组第一个元素的输入
实际的读取流程为:
- 调用
id = in.nextInt(),读取到100,缓冲区剩余内容为\n张三\n150\n - 调用
name = in.nextLine(),直接读取残留的\n,将name赋值为空字符串,缓冲区剩余内容为张三\n150\n - 循环中调用
arr[i] = in.nextInt(),此时需要解析int类型,但缓冲区首个内容是字符串“张三”,直接触发InputMismatchException,和你给出的堆栈报错完全匹配。
你观察到“将String类型变量与输入语句写在同一行就不报错”的现象,本质是该写法下你刚好调整了输入读取的匹配逻辑,和变量声明位置无关,完全可以保留类层级声明成员变量的写法。
可行解决方法
核心调整逻辑
- 全局共享同一个Scanner实例,避免多次创建Scanner绑定
System.in - 在
nextInt()调用后处理残留的换行符,修正输入序列错位问题 - 无需修改类层级的String成员变量声明逻辑
调整后完整代码
import java.util.*; class SugarSmashPlayer{ // 改为静态共享Scanner,所有实例共用同一个输入缓冲区 static Scanner in = new Scanner(System.in); int id;int n=0;String name; int[] arr=new int[40]; void get(){ id=in.nextInt(); in.nextLine(); // 吃掉id输入后残留的换行符 name=in.nextLine(); for(int i=0;i<10;){ arr[i]=in.nextInt(); n++; if(arr[i]>=100){i++;} else {i=11;} } } void set(){ System.out.println(id+" "+name+" "); for(int i=0;i<n;i++){System.out.println(arr[i]+" "); } } } class PremiumSugarSmashPlayer extends SugarSmashPlayer{ void get1(){n=0; id=in.nextInt(); in.nextLine(); // 同样处理残留换行 name=in.nextLine(); for(int i=0;i<40;){ arr[i]=in.nextInt(); n++; if(arr[i]>=100){i++;} else i=40;} } void set1(){ System.out.println(id+" "+name+" "); for(int i=0;i<n;i++){System.out.println(arr[i]+" "); } } } public class Game{ public static void main(String[] args){ SugarSmashPlayer box=new SugarSmashPlayer(); PremiumSugarSmashPlayer box1=new PremiumSugarSmashPlayer(); box.get(); box.set(); box1.get1(); box1.set1(); } }
额外注意事项
- 输入时需严格按照预期类型输入:id、数组元素均需输入整数,name行输入任意字符串即可
- 如果不需要读取带空格的姓名,也可以将
name = in.nextLine()改为name = in.next(),next()会自动跳过换行、空格等分隔符,无需额外处理残留换行
内容的提问来源于stack exchange,提问作者Princeofcoding
相关产品推荐
相关产品推荐

