Java中Scanner的Integer.parseInt(scanner.nextLine())和scanner.nextInt()的比较
Java中Scanner的Integer.parseInt(scanner.nextLine())和scanner.nextInt()的比较
在Java中,我们可以使用Integer.parseInt(Scanner.nextLine())和Scanner.nextInt()两种方法来从Scanner读取整数。然而,这两种方法之间存在一些差异。
本教程将对它们进行比较并讨论它们之间的不同之处。
使用Integer.parseInt(scanner.nextLine())和scanner.nextInt()读取整数
Scanner.nextLine()方法将整行作为字符串从扫描器中读取。因此,如果我们想要得到一个Integer类型的结果,我们必须自己将字符串转换为Integer,例如使用Integer.parseInt()方法。
另一方面,Scanner.nextInt()读取输入中的下一个记作为整数。在Scanner中,一个标记是由Scanner用于解析输入流的分隔符模式定义的。默认情况下,Scanner的分隔符模式是任何空白字符(例如空格、制表符或换行符)。
现在我们已经了解了这些方法的作用,让我们看看它们是如何从Scanner对象中读取整数的。首先,我们将向扫描器输入一个带有尾随换行符的字符串:
String input = "42\n";
为了简单起见,本教程将使用单元测试断言来验证结果。
首先,让我们使用Scanner.nextLine()方法获取数字42:
Scanner sc1 = new Scanner(input);
int num1 = Integer.parseInt(sc1.nextLine());
assertEquals(42, num1);
接下来,轮到Scanner.nextInt():
Scanner sc2 = new Scanner(input);
int num2 = sc2.nextInt();
assertEquals(42, num2);
正如上述两个测试所示,这两种方法都可以从Scanner对象中读取输入并正确地获取整数42。
接下来,让我们看看这两种方法的不同之处。
当输入是无效数字格式时
它们的第一个区别是,当输入不是有效的数字时,这两种方法会抛出不同的异常。
现在,让我们改变输入:
String input = "Nan\n";
当我们通过scanner.nextLine()读取输入并尝试将无效输入转换为整数时,它会抛出 NumberFormatException:
Scanner sc1 = new Scanner(input);
assertThrows(NumberFormatException.class, () -> Integer.parseInt(sc1.nextLine()));
这是因为sc1.nextLine()将下一行输入作为字符串读取。但是,后续的转换失败了。因此,Integer.parseInt()方法抛出了NumberFormatException。
值得一提的是,我们使用了JUnit 5的assertThrows()方法来断言方法调用抛出了NumberFormatException。
另一方面,当我们尝试使用Scanner.nextInt()将输入作为整数读取时,它会引发InputMismatchException:
Scanner sc2 = new Scanner(input);
assertThrows(InputMismatchException.class, sc2::nextInt);
Scanner.nextInt()方法不会消耗无效的标记
正如前面提到的,Scanner.nextLine()将输入中的下一行作为字符串读取。与Scanner.nextLine()方法不同,nextInt()将尝试将输入中的下一个标记解析为整数。
如果它无法解析一个标记,正如我们之前看到的,nextInt()会抛出InputMismatchException。但是我们应该注意到Scanner.nextInt()不会消耗它未能解析的解析失败的标记。
一个例子可以帮助我们快速理解这一点:
String input = "42 is a magic number\n";
// nextInt()
Scanner sc2 = new Scanner(input);
int num2 = sc2.nextInt();
assertEquals(42, num2);
// 再次调用nextInt()在"is"上引发异常
assertThrows(InputMismatchException.class, sc2::nextInt);
String theNextToken = sc2.next();
assertEquals("is", theNextToken);
正如上述例子所示,输入字符串有五个标记。第一个,“42”,是一个有效的整数。正如我们预期的,sc2.nextInt()调用得到了整数42。然后,我们再次调用了nextInt()并试图将标记“is”解析为整数。它抛出了InputMismatchException,这也是我们的预期。
接下来,我们调用了sc2.next()来获取下一个标记作为字符串。我们可以看到,标记“is”,nextInt()方法刚才未能解析的标记,被从输入中读取出来。换句话说,“is”没有被sc2.nextInt()方法消耗。
换行符处理
Java Scanner默认通过输入中的“\n”字符分隔行。接下来,让我们看看Scanner.nextLine()和nextInt()如何处理换行字符。
首先,我们准备一个多行字符串作为输入:
String input = new StringBuilder().append("42\n")
.append("It is a magic number.\n")
.toString();
Scanner.nextLine()方法消耗整行,包括行分隔符。但它只返回不带尾随换行字符的文本, 然后将位置设置为下一行的开头:
// nextLine()
Scanner sc1 = new Scanner(input);
int num1 = Integer.parseInt(sc1.nextLine());
String nextLineText1 = sc1.nextLine();
assertEquals(42, num1);
assertEquals("It is a magic number.", nextLineText1);
然而,另一方面,Scanner.nextInt()扫描输入的下一个标记作为整数,但不消耗随后的换行字符:
// nextInt()
Scanner sc2 = new Scanner(input);
int num2 = sc2.nextInt();
assertEquals(42, num2);
// nextInt()留下换行字符(\n)
String nextLineText2 = sc2.nextLine();
assertEquals("", nextLineText2);
在这个测试中,我们在调用sc2.nextInt()获取数字42后,调用了sc2.nextLine()。然后,正如我们所看到的,该方法返回了一个空字符串而不是“It is a magic number.”。这是因为nextInt()没有消耗“42”后的换行字符。
结论
在本文中,我们通过例子讨论了Integer.parseInt(Scanner.nextLine())和Scanner.nextInt()之间的差异。让我们在这里总结一下:
- 两种方法对于无效数字格式的输入抛出不同的异常。
Scanner.nextLine()消耗了Scanner中的换行字符,但返回的字符串中不包含它。Scanner.nextInt()不消耗换行字符。Scanner.nextInt()不消耗它未能解析的标记。
像往常一样,这里展示的所有代码片段都可以在GitHub上找到。