Add files via upload
This commit is contained in:
parent
3ee7e260dc
commit
243babc68e
|
@ -0,0 +1,212 @@
|
|||
## 实例1: 顾客购买650克西红柿需支付的金额
|
||||
在主方法中使用 try-catch 代码块将可能出现的异常语句进行异常处理。代码如下∶
|
||||
```java
|
||||
public class Tomato { // 创建西红柿类
|
||||
public static void main(String[] args) {
|
||||
try { // 把可能产生异常的Java代码放在try中
|
||||
String message = "西红柿:2.99元/500克"; // 西红柿的售价信息
|
||||
String[] strArr = message.split(":"); // 使用":"拆分字符串
|
||||
String unitPriceStr = strArr[2].substring(0, 4); // 截取西红柿单价:2.99
|
||||
double weight = 650; // 顾客购买西红柿的重量
|
||||
// 将String类型的西红柿单价转换为double类型
|
||||
double unitPriceDou = Double.parseDouble(unitPriceStr);
|
||||
// 输出顾客购买1.3斤的西红柿需支付的金额
|
||||
System.out.println(message + ",顾客买了" + weight + "克的西红柿,须支付"
|
||||
+ (float) (weight / 500 * unitPriceDou) + "元");
|
||||
} catch (Exception e) { // 捕捉与已产生的异常类型相匹配的异常对象
|
||||
e.printStackTrace(); // 打印异常信息
|
||||
}
|
||||
System.out.println("程序执行完毕!"); // 输出提示信息
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**注意∶** Exception是 try 代码块传递给catch代码块的异常类型,e是与已产生的异常类型相匹配的异常对象。
|
||||
|
||||
|
||||
运行结果中,程序仍然输出最后的提示信息"程序执行完毕!",这说明程序的执行没有因为产生异常被中断。由此可知,使用 try-catch代码块捕捉并处理异常时,不会因为产生异常影响程序的执行。
|
||||
|
||||
实例中,在catch代码块中使用了Exception 对象的printStackTrace()方法输出了异常信息,除此之外,Exception 对象还提供了其他的方法用于获取异常的相关信息∶
|
||||
- getMessage()方法: 获取有关异常事件的信息。
|
||||
- toString()方法: 获取异常的类型与性质。
|
||||
|
||||
|
||||
**注意∶** 有时为了编程简单会忽略catch代码块中的代码,这样trv-catch语句就成了一种摆设,一旦程序在运行过程中出现了异常,这个异常将很难查找。因此要养成良好的编程习惯∶ 在catch代码块中写入处理异常的代码.
|
||||
|
||||
思考:
|
||||
|
||||
#### 练习1
|
||||
在控制台上简述一个整型数组,如int a[] ={1,2,3,4 }; 数组遍历的过程,并体现出当i的值为多少时,会产生异常,异常的种类是什么?
|
||||
#### 练习2
|
||||
模拟一个简单的整数计算器(只能计算两个整数之间的加、减、乘、除的运算),并用try-catch捕捉InputMismatchException(控制台输入的不是整数)异常。
|
||||
|
||||
|
||||
## 实例2: 捕捉控制台输入西红柿单价后的异常
|
||||
西红柿的单价不是一成不变的,修改上面的实例,首先实现控制台输入单价的功能,然后在finally代码块中关闭控制台输入对象。
|
||||
```java
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Tomato { // 创建西红柿类
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in); // 创建控制台输入对象
|
||||
System.out.println("今天的西红柿单价(单价格式为“3.00”):"); // 控制台输出提示信息
|
||||
String dayPrice = sc.next(); // 把控制台输入的西红柿单价赋值给变量dayPrice
|
||||
if (dayPrice.length() == 4) { // 控制台输入的字符串长度为4时
|
||||
try { // 把可能产生异常的Java代码放在try中
|
||||
String message = "西红柿:" + dayPrice + "元/500克"; // 西红柿的售价信息
|
||||
String[] strArr = message.split(":"); // 使用":"拆分字符串
|
||||
String unitPriceStr = strArr[2].substring(0, 4); // 截取西红柿单价:2.99
|
||||
double weight = 650; // 顾客购买西红柿的重量
|
||||
// 将String类型的西红柿单价转换为double类型
|
||||
double unitPriceDou = Double.parseDouble(unitPriceStr);
|
||||
// 输出顾客购买650克的西红柿需支付的金额
|
||||
System.out.println(message + ",顾客买了" + weight + "克的西红柿,须支付"
|
||||
+ (float) (weight / 500 * unitPriceDou) + "元");
|
||||
} catch (ArrayIndexOutOfBoundsException aiobe) {// 捕捉数组元素下标越界异常对象
|
||||
aiobe.printStackTrace();
|
||||
} catch (Exception e) { // 捕捉与已产生的异常类型相匹配的异常对象
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
sc.close(); // 关闭控制台输入对象
|
||||
System.out.println("控制台输入对象被关闭。"); // 输出提示信息
|
||||
}
|
||||
} else { // 控制台输入的字符串长度不为4时
|
||||
// 输出提示信息
|
||||
System.out.println("违规操作:" + "输入西红柿单价时小数点后须保留两位有效数字(如3.00)!");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
从结果中可以看出厂程序在捕捉完异常信息之后,会执行finally代码块中的代码。另外,在以下3种特殊情况下finally块不会被执行∶
|
||||
- 在 finally 代码块中产生了异常。
|
||||
- 在前面的代码中使用System.exit()退出程序。
|
||||
- 程序所在的线程死亡。
|
||||
|
||||
|
||||
#### 练习3
|
||||
银行账号中现有余额 1023.79 元。模拟取款,当在控制台上输入的取款金额不是整数时,会引起数字格式转换异常。
|
||||
|
||||
#### 练习4
|
||||
新买了一台电脑,这台电脑与其他的电脑不一样,无法正常启动开机(电脑品牌未声明)。使用继承来体现这个事件,并尝试利用"电脑品牌"引出空指针异常。
|
||||
|
||||
|
||||
## 实例3: 规定西红柿单价不得超过7元
|
||||
当某种商品的价格过高时,国家会对这种商品采取宏观调控,进而使得这种商品的价格趋于稳定编写一个程序,规定西红柿单价不得超过7元,超过7元的情况作为异常抛出。
|
||||
```java
|
||||
import java.util.Scanner;
|
||||
|
||||
class PriceException extends Exception { // 自定义价格异常类,并继承异常类
|
||||
public PriceException(String message) { // 创建价格异常类有参构造方法
|
||||
super(message); // 调用异常类的有参构造方法
|
||||
}
|
||||
}
|
||||
|
||||
public class Tomato { // 创建西红柿类
|
||||
private double price; // 西红柿单价
|
||||
|
||||
public double getPrice() { // 获取西红柿单价
|
||||
return price;
|
||||
}
|
||||
|
||||
// 设置西红柿单价,如果产生价格异常,那么就抛出价格异常
|
||||
public void setPrice(double price) throws PriceException {
|
||||
if (price > 7.0) { // 如果西红柿单价大于7元
|
||||
throw new PriceException("国家规定西红柿单价不得超过7元!!!"); // 抛出价格异常
|
||||
} else { // 如果西红柿单价不大于7元
|
||||
this.price = price; // 为西红柿类的price属性赋值
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in); // 创建控制台输入对象
|
||||
System.out.println("今天的西红柿单价(单价格式为“3.00”):"); // 控制台输出提示信息
|
||||
String dayPrice = sc.next(); // 把控制台输入的西红柿单价赋值给变量dayPrice
|
||||
if (dayPrice.length() == 4) { // 控制台输入的字符串长度为4时
|
||||
// 将String类型的西红柿单价转换为double类型
|
||||
double unitPriceDou = Double.parseDouble(dayPrice);
|
||||
Tomato tomato = new Tomato(); // 创建西红柿对象
|
||||
try { // 把可能产生异常的Java代码放在try中
|
||||
tomato.setPrice(unitPriceDou); // 西红柿对象调用设置西红柿单价的方法
|
||||
} catch (Exception e) { // 捕捉数组元素下标越界异常对象
|
||||
System.out.println(e.getMessage()); // 输出异常信息
|
||||
} finally {
|
||||
sc.close(); // 关闭控制台输入对象
|
||||
}
|
||||
} else { // 控制台输入的字符串长度不为4时
|
||||
// 输出提示信息
|
||||
System.out.println("违规操作:" + "输入西红柿单价时小数点后须保留两位有效数字(如3.00)!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 实例4: 抛出控制台输入西红柿单价后的异常
|
||||
修改上面实例2,在西红柿类Tomato中,创建支付方法pay(String dayPrice, double weight), 在支付方法中抛出 ArrayIndexOutOfBoundsException异常。
|
||||
```java
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Tomato {// 创建西红柿类
|
||||
// 参数为西红柿单价和西红柿重量的支付方法,且支付方法抛出了数组元素下标越界异常
|
||||
public void pay(String dayPrice, double weight) throws ArrayIndexOutOfBoundsException {
|
||||
String message = "西红柿:" + dayPrice + "元/500克"; // 西红柿的售价信息
|
||||
String[] strArr = message.split(":"); // 使用":"拆分字符串
|
||||
String unitPriceStr = strArr[2].substring(0, 4); // 截取西红柿单价:2.99
|
||||
// 将String类型的西红柿单价转换为double类型
|
||||
double unitPriceDou = Double.parseDouble(unitPriceStr);
|
||||
// 输出顾客购买650克的西红柿需支付的金额
|
||||
System.out.println(message + ",顾客买了" + weight + "克的西红柿,须支付"
|
||||
+ (float) (weight / 500 * unitPriceDou) + "元");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in); // 创建控制台输入对象
|
||||
System.out.println("今天的西红柿单价(单价格式为“3.00”):"); // 控制台输出提示信息
|
||||
String dayPrice = sc.next(); // 把控制台输入的西红柿单价赋值给变量dayPrice
|
||||
if (dayPrice.length() == 4) { // 控制台输入的字符串长度为4时
|
||||
double weight = 650; // 顾客购买西红柿的重量
|
||||
try { // 把可能产生异常的Java代码放在try中
|
||||
Tomato tomato = new Tomato();
|
||||
tomato.pay(dayPrice, weight);
|
||||
} catch (ArrayIndexOutOfBoundsException aiobe) {// 捕捉数组元素下标越界异常对象
|
||||
System.out.println("pay方法抛出数组元素下标越界异常!"); // 输出提示信息
|
||||
} finally {
|
||||
sc.close(); // 关闭控制台输入对象
|
||||
System.out.println("控制台输入对象被关闭。"); // 输出提示信息
|
||||
}
|
||||
} else { // 控制台输入的字符串长度不为4时
|
||||
// 输出提示信息
|
||||
System.out.println("违规操作:" + "输入西红柿单价时小数点后须保留两位有效数字(如3.00)!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
使用throws关键字将方法产生的异常抛给上一级后,如果上以继续向上抛出,但最终要有能够捕捉并处理这个异常的代码。
|
||||
|
||||
#### 练习5
|
||||
模拟老师上课前的点名过程,并将旷课的学生作为异常抛出∶张三、李四、王五(老师在点名册上记下了“王五旷课”)。
|
||||
|
||||
#### 练习6
|
||||
超市经常会对定价较市场价低的产品实施限购∶ 超市里的鲜鸡蛋每500 克 3.98 元,每人限购1500克。现将超过1500克的作为异常抛出,而对于满足条件的,计算出应付款。
|
||||
|
||||
|
||||
##### 知识补充:
|
||||
throws 关键字和 throw 关键字的区别如下∶
|
||||
- throws 用在方法声明后面,表示抛出异常,由方法的调用者处理,而throw用在方法体内,用来制造一个异常,由方法体内的语句处理。
|
||||
- throws是声明这个方法会抛出这种类型的异常,以便使它的调用者知道要捕捉这个异常,而 throw是直接抛出一个异常实例。
|
||||
- throws表示出现异常的一种可能性,并不一定会产生这些异常,但如果使用throw就一定会产生某种异常。
|
||||
|
||||
|
||||
|
||||
|
||||
**异常的使用原则:**
|
||||
|
||||
异常处理的主要作用是捕捉并处理程序在运行时产生的异常。编写代码处理某个方法可能出现的异常时,可遵循以下原则∶
|
||||
- 不要过度使用异常。虽然通过异常可以增强程序的健壮性,但使用过多不必要的异常处理,可能会影响程序的执行效率;
|
||||
- 不要使用过于庞大的try-catch块。在一try块中放置大量的代码,这种写法看上去"很简单",但是由于try块中的代码过于庞大,业务过于复杂,会增加try块中出现异常的几率,从而增加分析产生异常原因的难度;
|
||||
- 避免使用catch(Exception e), 如果所有异常都采用相同的处理方式,那么将导致无法对不同异常进行分类处理;
|
||||
- 不要忽略捕捉到的异常,遇到异常一定要及时处理;
|
||||
- 如果父类抛出多个异常,则覆盖方法必须抛出相同的异常或其异常的子类,不能抛出新异常。
|
||||
|
Loading…
Reference in New Issue