Add files via upload

This commit is contained in:
OrangeCat 2021-07-22 12:58:54 +08:00 committed by GitHub
parent 3ee7e260dc
commit 243babc68e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 212 additions and 0 deletions

View File

@ -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[] ={1234 }; 数组遍历的过程,并体现出当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), 如果所有异常都采用相同的处理方式,那么将导致无法对不同异常进行分类处理;
- 不要忽略捕捉到的异常,遇到异常一定要及时处理;
- 如果父类抛出多个异常,则覆盖方法必须抛出相同的异常或其异常的子类,不能抛出新异常。