你好!
我们今天的课程会很特别!
在以前,完成任务和编写程序的过程很简单:我们编写一些代码,运行 main() 方法,程序做要做的事情,就行了。
但现在一切都将改变。今天我们将学习如何切实与程序互动:我们将教它如何对我们的操作做出反应!
在我们开始分析代码之前,你有没有处理过像扫描仪这样的设备?可能处理过。扫描仪的内部非常复杂,但其工作原理非常简单:读取用户提供的数据(如护照或保单),并将这些信息存储在内存中(例如,以图像的方式)。
今天,我们会创建自己的扫描仪。当然,它不能处理纸质文件,但处理文本不成问题 :)
让我们开始吧!
糟糕。我们有大麻烦了-_-为了避免这种情况,我们需要想出一种方法来验证用户输入的数据。例如,如果用户输入的不是数字,那么最好显示一个警告,说明输入的信息不是数字。如果信息没问题,就可以确认。但这需要我们“展望未来”,看看信息流会显示什么。Scanner 可以实现此功能吗?如何实现!可以采用许多方法来实现此功能:hasNextInt() — 该方法会检查下一个输入数据块是否是数字(根据需要返回 true 或 false)。hasNextLine() — 该方法会检查下一个输入块是否是字符串。hasNextByte(), hasNextShort()、hasNextLong()、hasNextFloat()、hasNextDouble() — 所有这些方法都对其余的数据类型执行类似的检查。现在试试改变数字读取程序:
Java 的 Scanner 类
首先,我们必须熟悉 java.util.Scanner 类。它的功能非常简单。与真正的扫描仪一样,它从你指定的来源读取数据。例如字符串、文件和控制台。接下来,它识别信息并进行相应的处理。下面是最简单的示例:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner("无论我将穿过的那扇门有多窄,\n" +
"无论我将肩承多大的惩罚,\n" +
"我是我命运的主宰,\n" +
"我是我灵魂的统帅");
String s = scanner.nextLine();
System.out.println(s);
}
}
我们已经创建了一个扫描仪对象,并指定了它的数据源(文本字符串)。nextLine() 方法访问数据源(即含四行诗的文本),找到下一个未读的行(在本例中是第一行),再将其返回。然后在控制台上显示出来:控制台输出:
无论我将穿过的那扇门有多窄,
我们可以多次使用 nextLine() 方法并显示整个诗的摘录:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner("无论我将穿过的那扇门有多窄,\n" +
"无论我将肩承多大的惩罚,\n" +
"我是我命运的主宰,\n" +
"我是我灵魂的统帅");
String s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
}
}
我们的扫描仪每次前进一步,读取下一行。该程序的输出显示如下:
无论我将穿过的那扇门有多窄,
无论我将肩承多大的惩罚,
我是我命运的主宰,
我是我灵魂的统帅
正如我们已经说过的,扫描仪的数据源不一定是字符串。例如,数据源可能是控制台。好消息是,以前,我们只显示数据,但现在将从键盘上读取数据!看看 Scanner 类还做了什么:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入数字:");
int number = sc.nextInt();
System.out.println("谢谢!你输入了数字 " + number);
}
}
nextInt() 方法读取并返回输入的数字。在程序中,我们使用该方法将值赋给变量 number。现在它更像一个真实的扫描仪了!程序会请求用户输入任何数字。在用户输完后,程序感谢用户,显示结果,然后结束。但仍存在严重问题。用户可能错误输入了内容。下面是当前程序停止工作的一个例子:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入数字:");
int number = sc.nextInt();
System.out.println("谢谢!你输入了数字 " + number);
}
}
现在尝试输入字符串“CodeGym”而不是数字:控制台输出:
输入数字:
CodeGym
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Main.main(Main.java:10) Process finished with exit code 1

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入数字:");
if (sc.hasNextInt()) {
int number = sc.nextInt();
System.out.println("谢谢!你输入了数字 " + number);
} else {
System.out.println("抱歉,这显然不是数字。重启程序,再试一次!");
}
}
}
现在我程序检查下一个输入的字符是否是数字。并且仅当它是数字时才显示确认。如果输入没有通过检查,程序会记录下来并要求用户再试一次。
基本上,你可以与 Scanner 对象通信,提前了解需要输入的数据类型。数字、字符串或其他?数字?什么类型?int、short、long?
这种灵活性使你有机会构建依赖于用户行为的程序逻辑。我们应该注意另一个重要的方法:useDelimiter()。
你将字符串传入此方法。该字符串包含要用作分隔符的字符。
例如,假设我们突然对日本诗歌感兴趣,并决定使用扫描仪读取大诗人松尾芭蕉写的一些俳句。
即使三段不同的诗歌是以一个很难看的字符串形式传递的,我们仍可以轻松拆分并优美呈现出来:
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner("在枯萎的树枝上'" +
"一只乌鸦落了下来。'" +
"正值秋天暮色沉沉。" +
"''***''" +
"朦胧月儿悬于天际,'" +
"就像一颗无根之树:'" +
"皎洁切痕一览无余。" +
"''***''" +
"江河泛滥滚滚而下!'" +
"苍鹭的短腿在水中艰难而行,'" +
"齐膝深水一片茫茫。");
scan.useDelimiter("'");
while (scan.hasNext()) {
System.out.println(scan.next());
}
scan.close();
}
}
我们使用 "\n/*/*/*"(新行字符和三个星号)作为分隔符。最后,我们得到漂亮的控制台输出,就像在书中一样:
在枯萎的树枝上
一只乌鸦落了下来。
正值秋天暮色沉沉。
***
朦胧月儿悬于天际,
就像一颗无根之树:
皎洁切痕一览无余。
***
江河泛滥滚滚而下!
苍鹭的短腿在水中艰难而行,
齐膝深水一片茫茫。
此示例还有一个方法必须提出来:close()。像任何处理 I/O 流的对象一样,扫描仪在完成后必须关闭,这样它就不会消耗计算机的资源。绝不要忘记使用 close() 方法!
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入数字:");
int number = sc.nextInt();
System.out.println("谢谢!你输入了数字 " + number);
sc.close(); // 现在我们完成了所有事情!
}
}
今天就讲到这里!正如你所见,Scanner 类很有用,可轻松使用!:)
GO TO FULL VERSION