行业知识
《Java黑皮书基础篇第10版》 第12章【习题】
Java语言程序设计 习题第十二章
12.2章节习题
12.1 使用异常处理的优势是什么?
如果没有异常处理,方法执行(called method)出错时,调用者(caller)没有办法进行处理(比如方法所在的类被封装,调用者无法访问),而方法通常也不具备处理异常的能力,导致程序执行被终止
通过异常处理,方法执行出错时,异常会被方法抛出,并由调用者捕获,调用者可以自行调试,改正异常使程序继续执行
12.2 下面哪些语句会抛出一个异常?
System.out.println(1 / 0); //throw an exceptionSystem.out.println(1.0 / 0); //Output: Infinity
12.3 指出下面代码中的问题。代码会抛出任何异常吗?
long value = Long.MAX_VALUE + 1;System.out.println(value);
不会,计算机使用二进制储存数字,其中首位用1表示整数,0表示负数。最大值+1会使首位的1变成0,从而输出一个很大的负数
System.out.println(Long.toUnsignedString(value));
可以使用以上方法输出无符号整数值
12.4 当产生一个异常的时候,JVM 会做什么?如何捕获一个异常?
当遇到异常的时候,JVM会寻找catch语句来捕获异常。应该使用try-catch语句(statement)来捕获异常
12.5 下面代码的输出是什么?
public class Test { public static void main(String[] args) {try { int value = 30; if (value value is too smallContinue after the catch block
如果把语句
int value = 30;
换成
int value = 50;
会输出什么结果?
Continue after the catch block
12.6 给出下面代码的输出。
public class Test {public static void main(String[] args) {for (int i = 0; i 0 1
public class Test {public static void main(String[] args) {try {for (int i = 0; i 0
try遇到异常时,try块内剩余的代码就不再执行
12.3章节习题
12.7 描述Java的Throwable类,它的子类以及异常的类型。
Throwable类是所有异常类直接或间接的父类,他有两个子类,Error和Exception。
Error是指错误,通常是系统内部的几乎不可修复的错误。
Exception是由程序或外部环境引起的错误,程序猿可以捕获抛出的异常并处理
在Exception中,有一个runtime exception,是指程序的设计错误,通常是程序的编写逻辑错误
12.8 下面的程序如果将抛出RuntimeException,那么会抛出哪种?
public class Test {public static void main(String[] args) { //ArithmeticExceptionSystem.out.println(1 / 0); }} public class Test {public static void main(String[] args) { //IndexOutOfBoundExceptionint[] list = new int[5];System.out.println(list[5]);}} public class Test {public static void main(String[] args) { //IndexOutOfBoundExceptionString s = "abc";System.out.println(s.charAt(3));}} public class Test {public static void main(String[] args) { //ClassCastExceptionObject o = new Object();String d = (String)o;}} public class Test {public static void main(String[] args) { //NullPointerExceptionObject o = null;System.out.println(o.toString());}} public class Test {public static void main(String[] args) { //No ExceptionSystem.out.println(1.0 / 0); }} 12.4章节习题
12.9 声明异常的目的是什么? 怎样声明一个异常,在哪里声明? 在一个方法头中可以声明多个异常吗?
如果一个必检异常在方法头使用throws被声明,那么调用者必须显示的捕获它。
可以用逗号隔开,在方法头声明多个异常
12.10 什么是必检异常?什么是免检异常?
必检异常是除了Error和runtimeException外的异常
12.11 如何抛出一个异常? 可以在一个throw语句中抛出多个异常吗?
使用throw在方法体中抛出一个异常,1个throw语句只能抛出1个异常
12.12 关键字throw的作用是什么?关键字throws的作用是什么?
抛出异常和声明异常
12.13 假设下面的trycatch块中的statement2引起一个异常:
try { statement1; statement2; statement3;}catch (Exception1 ex1) { }catch (Exception2 ex2) { }statement4; 回答下列问题:
• 会执行statement3吗?
不会
• 如果异常未被捕获,会执行statement4吗?
不会,程序直接报错
• 如果在catch块中捕获了异常,会执行statement4吗?
会
12.14 运行下面程序时会显示什么?
public class Test {public static void main(String[] args) {try {int[] list = new int[10]; System.out.println("list[10] is " + list[10]);}catch (ArithmeticException ex) {System.out.println("ArithmeticException"); }catch (RuntimeException ex) { System.out.println("RuntimeException");}catch (Exception ex) {System.out.println("Exception"); }} } RuntimeException
12.15 运行下面程序时会显示什么?
public class Test {public static void main(String[] args) {try {method();System.out.println("After the method call");}catch (ArithmeticException ex) {System.out.println("ArithmeticException");}catch (RuntimeException ex) { System.out.println("RuntimeException");}catch (Exception e) {System.out.println("Exception"); }}static void method() throws Exception {System.out.println(1 / 0); }} ArithmeticException
12.16 运行下面程序时会显示什么?
method方法中的异常已经在method方法内部被捕获了,所以main方法就可以正常执行了
public class Test {public static void main(String[] args) {try {method();System.out.println("After the method call");}catch (RuntimeException ex) {System.out.println("RuntimeException in main"); }catch (Exception ex) { System.out.println("Exception in main");} }static void method() throws Exception { try {String s = "abc";System.out.println(s.charAt(3)); }catch (RuntimeException ex) { System.out.println("RuntimeException in method()");}catch (Exception ex) {System.out.println("Exception in method()"); }} } RuntimeException in method()After the method call
12.17 方法getMessage()可以做什么?
可以得到抛出异常时的异常消息
12.18 方法printStackTrace()可以做什么?
打印出方法调用的栈
12.19 没有异常发生时,try-catch块的存在会引起额外的系统开销吗?
不会
12.20 修改下面代码中的编译错误:
public void m(int value) { if (value 方法拋出的必检异常必须在方法头中使用throws显式声明
public void m(int value) throws Exception { if (value 12.5章节习题
本节章节习题有歧义,因此找来了原版英文书,发现题目是有差别的,在这里放上原版英文书的题目,原版英文书一共有两道题
12.21.1
Suppose you run the following code:
public static void main(String[] args) throws Exception2 { m(); statement7;} public static void m() { try { statement1; statement2; statement3; } catch (Exception1 ex1) { statement4; } finally { statement5; } statement6;} answer the questions:
- If no exception occurs, which statements are executed?
- If statement2 throws an exception of type Exception1, which statements are executed?
- If statement2 throws an exception of type Exception2, which statements are executed?
- If statement2 throws an exception that is neither Exception1 nor Exception2, which statements are executed?
1. statement1, statement2, statement3, statement5, statement6, statement7.2. statement1, statement2, statement4, statement5, statement6, statement7.3. statement1, statement2, statement5.4. statement1, statement2, statement5.
12.21.2
Suppose you run the following code:
public static void main(String[] args) { try { m(); statement7; } catch (Exception2 ex { statement8; }} public static void m() { try { statement1; statement2; statement3; } catch (Exception1 ex1) { statement4; } finally { statement5; } statement6;} answer the questions:
- If no exception occurs, which statements are executed?
- If statement2 throws an exception of type Exception1, which statements are executed?
- If statement2 throws an exception of type Exception2, which statements are executed?
- If statement2 throws an exception that is neither Exception1 nor Exception 2, which statements are executed?
1. statement1, statement2, statement3, statement5, statement6, statement7.2. statement1, statement2, statement4, statement5, statement6, statement7.3. statement1, statement2, statement5, statement8.4. statement1, statement2, statement5.
12.6章节习题
12.22 下面的方法检査一个字符串是否是数值宇符串:
public static boolean isNumeric(String token) { try { Double.parseDouble(token); return true; } catch (java.lang.NumberFormatException ex) { return false; }} 代码是正确的,但是最好使用if来判断
12.7章节习题
12.23 假设下面的语句中,statement2会引起一个异常:
try { statement1; statement2; statement3;}catch (Exception1 ex1) {}catch (Exception2 ex2) { throw ex2;}finally { statement4;}statement5; 回答以下问题:
• 如果没有异常发生,会执行语句 statement4 吗? 会执行语句 statement5 吗?
都会
• 如果异常类型是 Exception1,那么会执行 statement4 吗? 会执行 statement5 吗?
都会
• 如果异常类型是 Exception2,那么会执行 statement4 吗? 会执行 statement5 吗?
会执行4,不会执行5
• 如果异常类型不是 Exception1以及 Exception2 类型的,那么会执行 statement4 吗? 会执行 statement5 吗?
会执行4,不会执行5
12.8章节习题
12.24 如果第 16 行被下面一行所替代,将输出什么?
throw new Exception(“New info from method1");
public class Test {public static void main(String[]args) { try {method1();}catch (Exception ex) { ex.printStackTrace();}}public static void method1() throws Exception {try {method2();}catch (Exception ex) { //第16行,添加了原始异常的实例ex,打印异常栈时,异常不会丢失原始信息throw new Exception("New info from methodl", ex);}}public static void method2() throws Exception {throw new Exception("New info from method2");}} 12.9章节习题
12.25 如何定义一个自定义异常类?
继承一个Exception类或者他的子类
12.26 假定setRadius方法抛出程序清单12-10中定义的InvalidRadiusException异常,那么运行下面的程序时会显示什么?
public class Test {public static void main(String[] args) {try {method();System.out.println("After the method call");}catch (RuntimeException ex) {System.out.println("RuntimeException in main"); }catch (Exception ex) { System.out.println("Exception in main");} }static void method() throws Exception { try {Circle c1 = new Circle(1); c1.setRadius(-1); System.out.println(c1.getRadius());}catch (RuntimeException ex) {System.out.println("RuntimeException in method()"); }catch (Exception ex) { System.out.println("Exception in method()"); throw ex;} }} Exception in method()Exception in main
12.10章节习题
12.27 使用下面的语句创建File对象时,错在哪里?
new File("c:\book\test.dat"); 在Java中单个反斜杠是一个特殊的转义字符,应该使用双反斜杠来表示文件路径
12.28 如何检査一个文件是否已经存在? 如何删除一个文件? 如何重命名一个文件? 使用File类能够获得文件的大小(字节数)吗? 如何创建一个目录 ?
使用exists()方法
使用delete()方法
使用renameTo(File)方法
使用length()方法
使用mkdir()方法
12.29 能够使用File类进行输人/输出吗? 创建一个File对象就是在磁盘上创建一个文件吗?
不可以,不是
12.11章节习题
12.30 如何创建一个 PrintWriter 以向文件写数据? 在程序清单12-13 中,为什么要在 main 方法中声明 throws Exception? 在程序清单12-13中,如果不调用 close() 方法,将会发生什么?
PrintWriter output = new PrintWriter(filename);
因为I/O异常是必检异常,必须捕获或声明
数据就不能正确的保存
12.31 给出下面的程序执行之后,文件 temp.txt 的内容。
public class Test {public static void main(String[] args) throws Exception {java.io.PrintWriter output = new java.io.PrintWriter("temp.txt");output.printf("amount is %f %e\r\n", 32.32, 32.32); output.printf("amount is %5.4f %5.4e\r\n", 32.32, 32.32); output.printf("%6b\r\n", (1 > 2)); output.printf("%6s\r\n", "Java");output.close(); }} amount is 32.320000 3.232000e+01amount is 32.3200 3.2320e+01 false Java
12.32 使用 try-with-resource 语法重写前一题中的代码。
public class Test {public static void main(String[] args) throws Exception {try (java.io.PrintWriter output = new java.io.PrintWriter("temp.txt");) {output.printf("amount is %f %e\r\n", 32.32, 32.32); output.printf("amount is %5.4f %5.4e\r\n", 32.32, 32.32); output.printf("%6b\r\n", (1 > 2)); output.printf("%6s\r\n", "Java");}}} 12.33 如何创建一个Scanner从文件读数据? 在程序清单12-15中,为什么要在main方法中声明throws Exception? 在程序清单 12-15 中,如果不调用 close() 方法,将会发生什么?
Scanner input = new Scanner(fileName);
因为I/O异常是必检异常,必须捕获或声明
不会对程序运行有影响,但是释放文件占用的资源是一个好习惯
12.34 如果试图对一个不存在的文件创建Scanner, 将会发生什么情况? 如果试图对一个已经存在的文件创建PrintWriter, 会发生什么情况?
Scanner会报FileNotFoundException
文件会被新内容覆盖,原内容丢失
12.35 是否所有平台上的行分隔符都是一样的? Windows 平台上的行分隔符是什么?
Windows是\r\n,UNIX是\n
12.36 假设输入45 57.8 789, 然后点击回车键。显示执行完下面的代码之后变量的内容。
Scanner input = new Scanner(System.in); //45int intValue = input.nextInt();//57.8double doubleValue = input.nextDouble(); //789String line = input.nextLine();
12.37 假设输人45、回车键、57.8、回车键、789、回车键。显示执行完下面的代码之后变量的内容。
Scanner input = new Scanner(System.in); //45int intValue = input.nextInt();//57.8double doubleValue = input.nextDouble(); //emptyString line = input.nextLine();
对于nextInt()和nextDouble()方法,首先,他们会从当前的输入缓冲区开始,忽略所有的空格和换行符,直到遇到一个非空格非换行符的字符。
其次,开始记录接下来所有的字符,直到再次遇到空格或换行符时停止,并返回所有收集到的字符(只返回字符,不返回空格或换行符)
对于nextLine()方法,首先,他们会从当前的输入缓冲区开始,记录并返回所有的内容(包括空格和换行符),直到遇到换行符时停止,也就是读取当前行的全部剩余部分
注意,读取完成后,这个方法会将读取指针转入新的下一行
12.12章节习题
12.38 如何为从一个 URL 读取的文本创建一个 Scanner 对象?
Scanner input = new Scanner(url.openStream());
12.13章节习题
12.39 在一个 URL 添加到listOfPendingURLs之 前,第25行检査它是否被遍历过了。listOfPendingURLs是否可能包含重复的URLs呢?如果是,给出一个例子。
是的,如果说在查找URL A时,发现了在A中的两个URL B。这两个B都没有进入到TraversedList中,但是却都会进入PendingList中
编程练习题
*12.1 (NumberFormatException异常)
程序清单7-9是一个简单的命令行计算器。注意,如果某个操作数是非数值的,程序就会中止。编写一个程序,利用异常处理器来处理非数值操作数;然后编写另一个不使用异常处理器的程序,达到相同的目的。程序在退出之前应该显示一条消息,通知用户发生了操作数类型错误
//这个异常类在java.util包中需要导入,如果是java.lang包中的异常类就不需要导入了import java.util.InputMismatchException;import java.util.Scanner;public class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { System.out.println("请输入第一个数:"); double num1 = scanner.nextDouble(); System.out.println("请输入运算符(+、-、*、/):"); String operator = scanner.next(); System.out.println("请输入第二个数:"); double num2 = scanner.nextDouble(); calculator(num1, operator, num2); } catch (ArithmeticException ex){ System.out.println(ex); } catch (InputMismatchException ex) { System.out.println("Error: Input Mismatch"); } } public static void calculator(double num1, String operator, double num2) throws ArithmeticException{ double result = 0; switch (operator) { case "+": result = num1 + num2; break; case "-": result = num1 - num2; break; case "*": result = num1 * num2; break; case "/": if (num2 == 0) { throw new ArithmeticException("The second number cannot be 0"); } result = num1 / num2; break; default: System.out.println("输入的运算符有误"); return; } System.out.println("结果为:" + result); }} 输出结果:
请输入第一个数:3请输入运算符(+、-、*、/):/请输入第二个数:0java.lang.ArithmeticException: The second number cannot be 0
*12.2 (InputMismatchException异常)
编写一个程序,提示用户读取两个整数,然后显示它们的和。程序应该 在输人不正确时提示用户再次读取字。
//这个异常类在java.util包中需要导入,如果是java.lang包中的异常类就不需要导入了import java.util.InputMismatchException;import java.util.Scanner;public class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); boolean inputValid = false; //while循环条件为true时进入循环,!是逻辑运算符:非 //inputValid被初始化为false,!inputValid则为true,因此进入while循环 //也可以使用do-while循环,不论条件先运行一遍,就不需要!逻辑运算符了 while (!inputValid) { try { System.out.println("请输入第一个数:"); double num1 = scanner.nextDouble(); System.out.println("请输入第二个数:"); double num2 = scanner.nextDouble(); calculator(num1, num2); //如果程序顺利计算了两数之和,就把inputValid改为true,!inputValid则为false,就会退出循环 //如果程序被异常捕获,就不会执行下面的代码,重新进入循环 inputValid = true; } catch (InputMismatchException ex) { System.out.println("Error: Input Mismatch"); //下面这一行代码很关键。如果没有这行代码,程序会陷入***循环 //我们在输入完一个非法字符之后会按回车键,会被异常捕获,此时输入缓冲区留下一个回车字符,但nextDouble()方法只能读取数字,不读取回车字符,当前的输入缓冲区依然有一个回车符 //再次进入循环时,程序会认为这个遗留的回车符是一个用户输入的非法字符,就直接被异常捕获,由于nextDouble()方法只会读取数字,回车字符不会被清空,所以陷入***循环 scanner.nextLine(); } } scanner.close(); } public static void calculator(double num1, double num2) { System.out.println(num1 + num2); }} 输出结果:
请输入第一个数:aError: Input Mismatch请输入第一个数:1请输入第二个数:12.0
*12.3 (ArraylndexOutBoundsException异常)
编写一个满足下面要求的程序:
• 创建一个由 100 个随机选取的整数构成的数组。
• 提示用户输人数组的下标,然后显示对应的元素值。如果指定的下标越界,就显示消息Out of Bounds.
import java.util.Scanner;public class Test {public static void main(String[] args) {int[] test = new int[100];for (int i = 0; i 输出结果:
Input an index to check: 100Out of Bounds
*12.4 (IllegalArgumentException异常)
修改程序清单10-2中的Loan类,如果贷款总额、利率、年数小于或等于零,则抛出IllegalArgumentException异常
Test.java
public class Test {public static void main(String[] args) {try {Loan loan1 = new Loan(0, 4, 1000);}catch (IllegalArgumentException ex){ex.printStackTrace();}try {Loan loan2 = new Loan(4, 0, 1000);}catch (IllegalArgumentException ex){ex.printStackTrace();}try {Loan loan3 = new Loan(4, 4, 0);}catch (IllegalArgumentException ex){ex.printStackTrace();}Loan loan4 = new Loan(4, 1, 1000);try {loan4.setAnnualInterestRate(0);}catch (IllegalArgumentException ex) {ex.printStackTrace();}try {loan4.setLoanAmount(0);}catch (IllegalArgumentException ex) {ex.printStackTrace();}try {loan4.setNumberofYears(0);}catch (IllegalArgumentException ex) {ex.printStackTrace();}}} Loan.java
public class Loan {private double annualInterestRate; private int numberofYears; private double loanAmount;private java.util.Date loanDate;//Default constructorpublic Loan() {this(2.5, 1, 1000);}public Loan(double annualInterestRate, int numberofYears, double loanAmount) {if (annualInterestRate throw new IllegalArgumentException("Index