一. 异常的体系
二. 代码层面如何应对异常?
(一)抛出异常(throws)
在方法上使用throws关键字,可以将方法内部出现的异常跑出去给调用者处理
方法 throws 异常1, 异常2, 异常3 .. {
...
}
(二)捕获异常(try...catch)
直接捕获程序出现的异常
try {
//监视可能出现的异常代码
}catch(异常类型1 变量) {
//处理异常
}catch(异常类型2 变量) {
//处理异常
}...
三. 自定义异常
(一)介绍
虽然java提供了很多异常类,但并不能够为世界上全部的问题都提供异常类来代表,如果企业自己的某种问题想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了
(二)自定义异常的种类
1. 自定义运行时异常
- 定义一个异常类继承RuntimeException
- 重写构造器
- 通过throw new 异常类(xxxx)来创建异常对象并抛出。
编译阶段不报错,提醒不强烈,运行时才可能出现!!
例如在下面的例子中,我们编写一个年龄不合法的异常:
public class ExceptionTest1 {
public static void main(String[] args) {
//需求:保存一个合法年龄
try {
saveAge(23);
System.out.println("底层是执行成功的! ");
} catch (Exception e) {
e.printStackTrace();
System.out.println("底层出现了bug!");
}
}
public static void saveAge(int age) {
if (age > 0 && age < 150) {
System.out.println("年龄被成功保存: " + age);
} else {
//1. 用一个异常对象封装这个问题
//2. throw 抛出去这个异常对象
throw new AgeIllegalRuntimeException("/age is illegal,your age is " + age);
}
}
}
编写异常类:
//1. 必须让这个类继承自RuntimeException,才能成为一个运行时异常
public class AgeIllegalRuntimeException extends RuntimeException {
public AgeIllegalRuntimeException() {
}
public AgeIllegalRuntimeException(String message) {
super(message);
}
}
2. 自定义编译时异常
- 定义一个异常类继承Exception
- 重写构造器
- 通过throw new 异常类(xxxx)来创建异常对象并抛出。
其实创建这个异常类的过程和创建运行时异常类的过程基本上是一致的,只是不继承RuntimeException而是继承Exception类罢了。但是在使用这个异常的时候需要注意:
public static void saveAge(int age) throws AgeIllegalRuntimeException {
if (age > 0 && age < 150) {
System.out.println("年龄被成功保存: " + age);
} else {
//1. 用一个异常对象封装这个问题
//2. throw 抛出去这个异常对象
throw new AgeIllegalRuntimeException("/age is illegal,your age is " + age);
}
}
首先,我们要用throw去抛出这个异常对象,接着在方法上用throws抛出方法内部的异常。
public static void main(String[] args) {
//需求:保存一个合法年龄
try {
saveAge(223);
System.out.println("底层是执行成功的! ");
} catch (AgeIllegalRuntimeException e) {
e.printStackTrace();
System.out.println("底层出现了bug!");
}
}
在catch时直接catch异常对象。
那么我们以后到底使用运行时异常还是编译时异常呢?如果某个问题程序员经常去犯,很严重,我们要比较强烈的去提醒程序员,就要用到编译时异常
四. 非代码层面处理异常的方式
(一)捕获异常,记录异常并相应合适的信息给用户
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionTest2 {
public static void main(String[] args) {
try {
test1();
} catch (FileNotFoundException e) {
System.out.println("您要找到的文件不存在");
e.printStackTrace(); //打印出这个异常对象,并记录下来
} catch (ParseException e) {
System.out.println("您要解析的时间有问题了!");
e.printStackTrace(); //打印出这个异常对象,并记录下来
}
}
public static void test1() throws FileNotFoundException, ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse("2028-11-11 10:24");
System.out.println(d);
test2();
}
public static void test2() throws FileNotFoundException {
//读取文件的
InputStream isr = new FileInputStream("D:/meinv.png");
}
}
对上面的代码进行写法上的优化:
我们可以将所有的异常对象改为Exception而不是特定的异常对象:
public class ExceptionTest2 {
public static void main(String[] args) {
try {
test1();
} catch (Exception e) {
System.out.println("您当前的操作有问题");
e.printStackTrace(); //打印出这个异常对象,并记录下来
}
}
public static void test1() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse("2028-11-11 10:24");
System.out.println(d);
test2();
}
public static void test2() throws Exception {
//读取文件的
InputStream isr = new FileInputStream("D:/meinv.png");
}
}
(二)捕获异常,尝试重新修复
如例:
import java.util.Scanner;
public class ExceptionTest3 {
public static void main(String[] args) {
//需求:调用一个方法,让用户输入一个合适的价格返回为止
while (true) {
try {
System.out.println(getMoney());
} catch (Exception e) {
System.out.println("请您输入合法的数字!");
}
}
}
public static double getMoney() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请您输入合适的价格:");
double money = sc.nextDouble();
if (money >= 0) {
return money;
} else {
System.out.println("您输入的价格是不合适的");
}
}
}
}