Scanner
介绍
Scanner 类是 Java 中一个用于读取用户输入的类,它可以从标准输入、文件、字符串等多种输入源中读取数据,并将数据转换为 Java 中的各种数据类型。
Scanner 在 java.util 包中定义,需要使用 import 指令导入 java.util 包。
因为输入对所有人可见,所以 Scanner 类不适合从控制台读取密码。
Scanner 使用步骤:
-
导入该类所在的包(要使用一个类的话就必须先导入该类所在的包)
-
创建该类的对象
-
调用里面的功能
Scanner 能转换成的数据类型:
1️⃣ 基本数据类型:
| 方法 | 读取类型 | 示例 |
|---|---|---|
| nextByte() | byte | byte b = scanner.nextByte(); |
| nextShort() | short | short s = scanner.nextShort(); |
| nextInt() | int | int i = scanner.nextInt(); |
| nextLong() | long | long l = scanner.nextLong(); |
| nextFloat() | float | float f = scanner.nextFloat(); |
| nextDouble() | double | double d = scanner.nextDouble(); |
| nextBoolean() | boolean | boolean flag = scanner.nextBoolean(); |
2️⃣ 字符串类型:
// 读取到空白符结束(空格、制表符、换行)
String word = scanner.next();
// 读取整行(包括空格)
String line = scanner.nextLine();
3️⃣ 大整数和大十进制数:
// 任意精度的整数
BigInteger bigInt = scanner.nextBigInteger();
// 任意精度的小数
BigDecimal bigDecimal = scanner.nextBigDecimal();
4️⃣ nextLine() 方法:只有遇到回车符才停下。
Scanner 有两套系统:next() 系列方法和 nextLine() 方法。
第一套系统 next() 系列方法:
next()
nextByte()
nextShort()
nextInt()
nextLong()
nextFloat()
nextDouble()
nextBoolean()
第二套系统:
nextLine(); // 接收一行输入
程序示例:
import java.util.Scanner;
import java.math.BigInteger;
import java.math.BigDecimal;
public class ScannerDataTypes {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("=== 输入各种类型的数据 ===");
// 1. 整数类型
System.out.print("输入byte值(-128~127):");
byte byteVal = scanner.nextByte();
System.out.println("byte: " + byteVal);
System.out.print("输入short值:");
short shortVal = scanner.nextShort();
System.out.println("short: " + shortVal);
System.out.print("输入int值:");
int intVal = scanner.nextInt();
System.out.println("int: " + intVal);
System.out.print("输入long值:");
long longVal = scanner.nextLong();
System.out.println("long: " + longVal);
// 2. 浮点类型
System.out.print("输入float值:");
float floatVal = scanner.nextFloat();
System.out.println("float: " + floatVal);
System.out.print("输入double值:");
double doubleVal = scanner.nextDouble();
System.out.println("double: " + doubleVal);
// 3. 布尔类型
System.out.print("输入boolean值(true/false):");
boolean boolVal = scanner.nextBoolean();
System.out.println("boolean: " + boolVal);
// 4. 字符串类型
System.out.print("输入一个单词:");
String word = scanner.next();
System.out.println("单词: " + word);
scanner.nextLine(); // 消耗回车
System.out.print("输入一行文字:");
String line = scanner.nextLine();
System.out.println("整行: " + line);
// 5. 大数字类型
System.out.print("输入大整数:");
BigInteger bigInt = scanner.nextBigInteger();
System.out.println("BigInteger: " + bigInt);
System.out.print("输入大十进制数:");
BigDecimal bigDec = scanner.nextBigDecimal();
System.out.println("BigDecimal: " + bigDec);
scanner.close();
}
}
遇到错误类型会报错:
import java.util.Scanner;
public class ScannerDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入一个整数:");
int input = scanner.nextInt();
System.out.println(input);
}
}
执行结果:
请输入一个整数:10.1
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at ScannerDemo1.main(ScannerDemo1.java:7)
空白
Scanner 类用空白作为默认分隔符。
空白的定义
Scanner类使用 Character.isWhitespace() 方法来判定空白字符,包括以下字符:
| 字符 | Unicode | 描述 | 转义序列 |
|---|---|---|---|
| 空格 | U+0020 | 普通空格 | ' ' |
| 制表符 | U+0009 | Tab键 | '\t' |
| 换行符 | U+000A | 换行(LF) | '\n' |
| 回车符 | U+000D | 回车(CR) | '\r' |
| 换页符 | U+000C | 换页 | '\f' |
| 垂直制表符 | U+000B | 垂直Tab | '\u000B' |
演示所有空白字符:
import java.util.Scanner;
public class WhitespaceDemo {
public static void main(String[] args) {
// 演示各种空白字符作为分隔符
String text = "Hello\tWorld\nJava\r\nProgramming\fTest\u000BEnd";
Scanner scanner = new Scanner(text);
System.out.println("使用默认空白分隔符分割:");
int count = 1;
while (scanner.hasNext()) {
System.out.println(count++ + ": " + scanner.next());
}
scanner.close();
}
}
执行结果:
使用默认空白分隔符分割:
1: Hello
2: World
3: Java
4: Programming
5: Test
6: End
Character.isWhitespace() 方法的使用示例:
public class WhitespaceCheck {
public static void main(String[] args) {
char[] whitespaceChars = {
' ', // 空格
'\t', // 制表符
'\n', // 换行
'\r', // 回车
'\f', // 换页
'\u000B' // 垂直制表符
};
for (char c : whitespaceChars) {
System.out.printf("字符 '%s' (Unicode: U+%04X) 是空白吗?%b%n",
getCharName(c), (int) c, Character.isWhitespace(c));
}
// 检查其他字符
System.out.println("逗号是空白吗?" + Character.isWhitespace(','));
System.out.println("字母A是空白吗?" + Character.isWhitespace('A'));
}
private static String getCharName(char c) {
switch (c) {
case ' ':
return "空格";
case '\t':
return "制表符";
case '\n':
return "换行符";
case '\r':
return "回车符";
case '\f':
return "换页符";
default:
return String.valueOf(c);
}
}
}
执行结果:
字符 '空格' (Unicode: U+0020) 是空白吗?true
字符 '制表符' (Unicode: U+0009) 是空白吗?true
字符 '换行符' (Unicode: U+000A) 是空白吗?true
字符 '回车符' (Unicode: U+000D) 是空白吗?true
字符 '换页符' (Unicode: U+000C) 是空白吗?true
字符 '
' (Unicode: U+000B) 是空白吗?true
逗号是空白吗?false
字母A是空白吗?false
空白的处理
第一套系统
第一套系统 next() 系列方法会跳过前导空白,然后读取直到遇到空白,剩余输入存在于缓冲中,等待下一次读入。因此 next() 系列的方法不能 “吃掉” 换行符,换行符会停留在缓冲中。
程序示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("enter some words: ");
String s = sc.next();
System.out.println(s);
sc.close();
}
}
执行结果:
enter some words: xiao ming
xiao
前面的空白被丢弃了,遇到空白停止了读取。
程序示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter some words: ");
String s = sc.next();
System.out.print(s);
System.out.println("结束");
sc.close();
}
}
执行结果:
Enter some words: hello
hello结束
此处 “结束” 二字紧随其后输出,说明回车并没有被放在字符串中,其实也没有被丢弃,而是在缓冲中。next() 系列方法可以丢弃前面遇到的所有空白,包括换行。例如:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter some words: ");
String s1 = sc.next();
System.out.print(s1);
System.out.print("Enter some words again: ");
String s2 = sc.next();
System.out.print(s2);
System.out.println("结束");
sc.close();
}
}
执行结果:
Enter some words: hello
helloEnter some words again: world
world结束
第二次读取时,首先遇到的是输入 hello 之后的换行,但是会丢弃,所以 s2 不是换行。
程序示例:
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个整数:");
int num1 = sc.nextInt();
System.out.println(num1);
System.out.println("请输入第二个整数:");
int num2 = sc.nextInt();
System.out.println(num2);
}
}
执行结果:
请输入第一个整数:
123 456
123
请输入第二个整数:
456
可以看出,输出的 456 前面没有空格,这是因为在 nextInt() 读取下一个数字时自动去掉了 456 前面的空格。
程序示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a, b; // 没有被初始化,但是程序不出错
System.out.print("输入一个整数: ");
a = sc.nextInt();
System.out.print("输入另一个整数: ");
b = sc.nextInt();
System.out.println("两个整数的和为 " + (a + b));
sc.close();
}
}
执行结果:
输入一个整数: 198
输入另一个整数: 876
两个整数的和为 1074
第二套系统
第二套系统 nextLine() 方法可以接收一整行输入,直到遇到回车才停止接收数据。nextLine() 会将换行符读取进来,然后丢弃,即 nextLine() 并不会将换行符存储起来,而是丢弃,这样一来换行符就不在缓冲中了,相当于一个 nextLine() 和一个换行符进行了 “一换一”,可以利用这个特点,用 nextLine() 方法 “吃掉” 缓冲中的换行符。
next() 系列的方法和 nextLine() 方法都不会真正读入换行符,区别在于一个是仍让换行符呆在缓冲中,一个是将换行符从缓冲中拿走再丢弃。
程序示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("Enter some words:");
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
System.out.print(s1);
System.out.println("结束");
sc.close();
}
}
执行结果:
Enter some words:
hello world
hello world结束
前面的空白没有被跳过,而是全部存储起来了,通过结束二字的输出位置可以看出 nextLine() 不会将换行符读取进来。
程序示例:
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个字符串:");
String line1 = sc.nextLine();
System.out.println(line1);
System.out.println("请输入第二个字符串:");
String line2 = sc.nextLine();
System.out.println(line2);
}
}
执行结果:
请输入第一个字符串:
hello world
hello world
请输入第二个字符串:
早 上 好
早 上 好
nextLine() 跟在 next() 系列方法后面会有一个弊端,这是由缓冲中的换行符导致的:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int num1 = sc.nextInt();
System.out.println(num1);
System.out.println("请输入一个字符串:");
String line1 = sc.nextLine();
System.out.println(line1);
System.out.println("结束");
sc.close();
}
}
执行结果 1:
请输入一个数字:
12
12
请输入一个字符串:
结束
line1 读取到了一个换行符,但是不会将换行符存储进去,所以 line1 是空的,因此此处的 System.out.println(line1); 相当于 System.out.println("");,也相当于 System.out.println();,因此仅仅只打印了一个换行。
执行结果 2:
请输入一个数字:
123 456
123
请输入一个字符串:
456
结束
可以用 nextLine() 消耗掉一个换行符:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int num1 = sc.nextInt();
System.out.println(num1);
System.out.println("请输入一个字符串:");
sc.nextLine(); // 消耗掉一个换行符
String line1 = sc.nextLine();
System.out.println(line1);
System.out.println("结束");
sc.close();
}
}
执行结果:
请输入一个数字:
12
12
请输入一个字符串:
hello
hello
结束
程序示例:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个字符串:");
String line1 = sc.nextLine();
System.out.print(line1); // 是 print 而不是 println
System.out.println("请输入第二个字符串:");
String line2 = sc.nextLine();
System.out.println(line2);
}
}
执行结果:
请输入第一个字符串:
hello world
hello world请输入第二个字符串:
你 好
你 好
由此可见,nextLine() 不会把换行符存储在字符串中。nextLine() 可以将换行符从缓冲区中读取走且不放到字符串中,这样换行符既不在缓冲区,也不在换行符中,相当于丢弃了。但是 Scanner 的第一套用法是把所有输入中除了读取到的东西之外的东西全部放到缓冲区中等待下次读取。在第一套系统中,比如输入 123 456,但是会带着一个回车,然后只读取了 123,就剩下三个空格加数字 456 再加一个回车在内存中。如果输入的是 123, 那么读取走 123 放到对应的变量中,剩余一个换行符留在缓冲区中。第二套系统不会把换行符读进变量,不会把换行符保存在变量中,也不会把换行符留在缓冲区等待下一次读取。
浙公网安备 33010602011771号