本文为《Java 语言程序设计》第十版 章节笔记
12.1 引言
异常 就是一种对象,表示阻止正常进行程序执行的错误或情况。
12.2 异常处理概述
异常是从方法抛出的。方法的调用者可以捕获以及处理该异常。
不应该让方法来终止程序,应该由调用者决定是否终止程序。Java 可以让一个方法可以抛出一个异常,该异常可以被调用者捕获和处理。
throw 语句
的执行称为抛出一个异常。catch 块
中的代码执行处理异常。
catch(ExceptionName ex) ,标识符 ex 的作用很像是方法中的参数,称为 catch 块的参数。
一个异常可能是通过 try 块中的 throw 语句直接抛出,或者调用一个可能抛出异常的方法而抛出。
异常处理的最根本的优势就是将检测错误(由被调用的方法完成)从处理错误(由调用方法完成)中分离出来。
12.3 异常类型
异常的根类是 java.lang.Throwable
可以通过继承 Exception
或者 Exception
的子类来创建自己的异常类。
RuntimeException
、Error
以及它们的子类都称为免检异常(unchecked exception)。所有其他异常都成为必检异常(checked exception),意思是指编译器会强制程序员检查并通过 try-catch 块处理它们,或者在方法头进行声明。
12.4 关于异常处理的更多知识
Java 的异常处理模型基于三种操作:声明一个异常(declaring an exception)、抛出一个异常(throwing an exception)和捕获一个异常(catching an exception)。
12.4.1 声明异常
为了在方法中声明一个异常,就要在方法头中使用关键字 throws,如:public void myMethod() throws IOException。多个异常用逗号隔开。
注意:如果方法没有在父类中声明异常,那么就不能在子类中对其进行继承来声明异常。
12.4.2 抛出异常
抛出一个异常:检测到错误的程序可以创建一个合适的异常类型的实例并抛出它。
提示:声明异常的关键字是 throws,抛出异常的关键字是 throw。
12.4.3 捕获异常
如果在执行 try 块的过程中没有出现异常,则跳过 catch 子句。
如果 try 块中的某条语句抛出一个异常,Java 就会跳过 try 块中的剩余语句,然后开始查找处理这个异常的代码的过程。处理这个异常的代码称为异常处理器。
寻找处理器的过程称为捕获一个异常。
12.4.4 从异常中获取信息
12.5 finally 子句
无论异常是否产生,finally 子句总是会被执行的。即使在到达 finally 块之前有一个 return 语句,finally 块还是会执行。
注意:使用 finally 子句时可以省略掉 catch 块。
12.6 何时使用异常
当错误需要被方法的调用者处理的时候,方法应该抛出一个异常。
一般来说,一个项目中多个类都会发生的共同异常应该考虑作为一个异常类。对于发生在个别方法中的简单错误最好进行局部处理,无需抛出异常。
在代码中何时应该使用 try-catch 块呢?当必须处理不可预料的错误状况时应该使用它。
12.7 重新抛出异常
如果异常处理器不能处理一个异常,或者只是简单地希望它的调用者注意到该异常,Java 允许该异常处理器重新抛出异常。
try {
statements;
}
catch (TheException ex){
perform prerations before exits;
throw ex;
}
12.8 链式异常
catch 块重新抛出原始的异常后,有时候,可能需要同原始异常一起抛出一个新的异常(带有附加信息),这称为链式异常。
12.9 创建自定义异常类
可以通过派生 java.lang.Exception 类来定义一个自定义异常类。
12.10 File 类
File 类包含了获得一个文件/目录的属性,以及对文件/目录进行改名和删除的方法。
但是,File 类不包含读写文件内容的方法。
绝对文件名(absolute file name)是由文件名和它的完整路径以及驱动器字符组成。
绝对文件名 = 驱动器字符 + 完整路径 + 文件名
例如,c:\book\Welcome.java
是文件 Welcome.java 在 Window 操作系统的绝对文件名。
相对文件名 是相对当前工作目录的。
构建一个 File 实例并不会在机器上创建一个文件。不管文件是否存在,都可以创建任意文件名的 File 实例。可以调用 File 实例上的 exists()方法来判断这个文件是否存在。
在程序中,不要直接使用绝对文件名。
12.11 文件输入和输出
使用 Scanner 类从文件中读取文件数据,使用 PrintWriter 类向文本文件写入数据。
java.io.PrintWriter 类可用来创建一个文件并向文本文件写入数据。
必须使用 close() 方法关闭文件,如果没有调用该方法,数据就不能正确的保存在文件中。
使用 try-with-resources 自动关闭资源
JDK 7 提供了下面的额新的 try-with-resources 语法来自动关闭文件:
try ( 声明和创建资源 ) {
使用资源来处理文件;
}
资源必须是 AutoCloseable 的子类型,比如 PrinterWriter,具有一个 close()方法。
处理完后,资源的 close()方法自动调用以关闭资源。
使用 Scanner 读取数据
Scanner 如何工作
方法 nextByte()、nextShort()、nextInt()、nextLong()、nextFloat()、nextDouble()和 next() 等都称为 标记读取方法(token-reading method),因为它们会读取用分隔符分隔开的标记。默认情况下,分隔符是空格。可以使用 useDelimiter(String regex) 方法设置新的分隔符模式。
一个标记读取方法首先跳过任意分隔符(默认情况下是空格),然后去读一个以分隔符结束的标记,并把标记自动转换成相应的类型值。不匹配,抛出异常 java.util.InputMismatchException
。
方法 next() 和 enxtLine() 都会读取一个字符串。next() 方法读取一个由 分隔符 分隔的 字符串,但是 nextLine() 读取一个以换行符结束的行(不包括换行符)。
12.12 从 Web 上读取数据
-
为了读取一个文件,首先要使用
java.net.URL
类的这个构造方法,为该文件创建一个 URL 对象。
public URL(String spec) throws MalformedURLException
URL url = new URL("http://www.google.com/index.html");
-
创建一个 URL 对象后,使用 URL 类中定义的
openStream()
方法来打开输入流和用输入流创建如下 Scanner 对象。
Scanner input = new Scanner(url.openStream());
现在就可以从输入流中读取数据了,就如同从本地文件中的读取一样。
//web爬虫
import java.util.Scanner;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.io.FileNotFoundException;
import java.io.FileWrite;
public class Test {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter a URL: ");
String url = input.nextLine();
crawler(url); // Traverse the Web from the a starting url
}
public static void crawler(String startingURL) {
ArrayList<String> listOfPendingURLs = new ArrayList<>();
ArrayList<String> listOfTraversedURLs = new ArrayList<>();
listOfPendingURLs.add(startingURL);
while (!listOfPendingURLs.isEmpty() &&
listOfTraversedURLs.size() <= 10) {
String urlString = listOfPendingURLs.remove(0);
if (!listOfTraversedURLs.contains(urlString)) {
listOfTraversedURLs.add(urlString);
System.out.println("Craw " + urlString);
java.io.File file = new java.io.File("web-crawler.txt");
FileWrite fw = new FileWrite(file, true);
try {
PrintWriter output = new PrintWriter(file);
output.print(urlString);
output.close();
}catch(FileNotFoundException ex){
System.out.println(ex);
}
for (String s: getSubURLs(urlString)) {
if (!listOfTraversedURLs.contains(s))
listOfPendingURLs.add(s);
}
}
}
}
public static ArrayList<String> getSubURLs(String urlString) {
ArrayList<String> list = new ArrayList<>();
try {
java.net.URL url = new java.net.URL(urlString);
Scanner input = new Scanner(url.openStream());
int current = 0;
while (input.hasNext()) {
String line = input.nextLine();
current = line.indexOf("http:", current);
while (current > 0) {
int endIndex = line.indexOf("\"", current);
if (endIndex > 0) { // Ensure that a correct URL is found
list.add(line.substring(current, endIndex));
current = line.indexOf("http:", endIndex);
}
else
current = -1;
}
}
}
catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
}
return list;
}
}
END
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于