一个关于Scanner类下next Line()方法调用过程中出现的问题
程序员文章站
2022-07-13 21:18:05
...
一个关于Scanner类下next Line()方法调用过程中出现的问题
问题的出现
昨天在修改代码时我遇到了一个问题,话不多说,先上代码
这是修改前的代码:
import java.util.*;
class Demo{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num;
while(true){
//调用showQuestion方法打印题目
System.out.println("请输入题号(1为题号,其他数字退出):");
System.out.println();
num = sc.nextInt();
switch(num){
case 1 :
//获取字符
isEnglish();
break;
default :
//其他无关题目
return;
}
}
}
/**
1. 判断用户输入的字符是不是英文字符,如果是输出yes,不是输出no
**/
public static void isEnglish(){
Scanner sc = new Scanner(System.in);
char ch;
System.out.println("1. 判断用户输入的字符是不是英文字符,如果是输出yes,不是输出no");
//获取字符
ch = sc.nextLine().charAt(0);
//判断
if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z'){
System.out.println("Yes!");
}else{
System.out.println("No!");
}
return ;
}
}
现在的代码时可以成功执行的,后来我想要把获取字符放到方法外进行并加上返回值,所有对代码做出了修改。以下时修改后的代码:
import java.util.*;
class Demo{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num;
char ch;
while(true){
//调用showQuestion方法打印题目
showQuestion();
System.out.println("请输入题号(1为题号,其他数字退出):");
System.out.println();
num = sc.nextInt();
switch(num){
case 1 :
//获取字符
ch = sc.nextLine().charAt(0);
isEnglish(ch);
break;
default :
//其他无关题目
return;
}
}
}
/**
打印所有题目
**/
public static void showQuestion(){
System.out.println();
System.out.println("1. 判断用户输入的字符是不是英文字符,如果是输出yes,不是输出no");
//其他无关题目
System.out.println();
return;
}
/**
1. 判断用户输入的字符是不是英文字符,如果是输出yes,不是输出no
@param 传入一个任意字符
@return 返回输入字符是否为英文
**/
public static boolean isEnglish(char ch){
//判断
if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z'){
System.out.println("Yes!");
}else{
System.out.println("No!");
}
return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z';
}
}
但是,现在突然就在我输入完题号之后,程序突然就报错了,我根本还没有进行字符串的输入
刚开始我以为系统出问题了,又重新试了几次,一直没有给我输入的机会
解决方法
后来我通过询问老师加上查资料终于找到了解决方法:
- 将此处的nextLine()换成next()就可以执行了
- 在ch = sc.nextLine().charAt(0)之前加一行sc.nextLine();
错误原因
在我出错的代码中,由于我之前已经调用过sc对象获取题号,在获取题号时我的输入是:
1(回车键)
而在num = sc.nextInt();是只是从sc中取走了回车键之前的数字1,回车键依然留在sc中;
若是这时我调用next()、nextInt()、nextDouble()、nextByte等这些方法是完全没问题的,因为这些方法取数据时会忽略数据之前的空格/回车/制表符 等无效数据,直到遇到下一个空格/回车/制表符时截止。
但是nextLine()这个方法不同,他会将你sc中的当前所有数据获取出来,并清空sc;
所以当我调用这个方法时,我还没有输入任何内容,但是他已经读取到了之前留下的回车键,相当于我没有输入数据就直接按下回车键,所以我通过sc.nextLine()方法也就没有获取到任何数据,那么它调用charAt(0)方法自然就产生了下标越界的问题。
问题延伸
由此我又想到,我们之前使用的一次回车获取多个数据是否就是通过这个机制来实现的
我有写了以下代码来做测试
import java.util.*;
class Demo11{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str;
for(int i = 1 ; i <= 5 ; i++){
//输入5个字符串,用制表符Tab隔开
for(int j = 0; j < i; j++){
sc.next();
}
System.out.println("获取" + i + "次字符串之后:");
System.out.println(sc.nextLine());
System.out.println();
}
}
}
五次输入,我输入了同一个样的数据:
abcd 1234 ABCD 你好 ?!/
结果果然:
JDK版本:1.8.0_91
上一篇: JVM规范&源码|字符串长度限制问题