JVM 处理方式
:
1.把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
2.程序停止执行
1.异常体系
2.编译时异常和运行时异常
-
编译时异常
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
-
运行时异常
- 都是RuntimeException类及其子类
- 无需显示处理,也可以和编译时异常一样处理
3:throws方式处理异常
-
定义格式
public void 方法() throws 异常类名 { }
-
示例代码
public class ExceptionDemo { public static void main(String[] args) throws ParseException{ System.out.println("开始"); // method(); method2(); System.out.println("结束"); } //编译时异常 public static void method2() throws ParseException { String s = "2048-08-09"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); System.out.println(d); } //运行时异常 public static void method() throws ArrayIndexOutOfBoundsException { int[] arr = {1, 2, 3}; System.out.println(arr[3]); } }
- 这个throws格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try...catch …或者 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
- 运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给jvm处理
4:throw抛出异常
throw new 异常();
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
-
throws和throw的区别
throws throw 用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名 表示声明异常,调用该方法有可能会出现这样的异常 表示手动抛出异常对象,由方法体内的语句处理 -
示例代码
public class ExceptionDemo8 { public static void main(String[] args) { //int [] arr = {1,2,3,4,5}; int [] arr = null; printArr(arr);//就会 接收到一个异常. //我们还需要自己处理一下异常. } private static void printArr(int[] arr) { if(arr == null){ //调用者知道成功打印了吗? //System.out.println("参数不能为null"); throw new NullPointerException(); //当参数为null的时候 //手动创建了一个异常对象,抛给了调用者,产生了一个异常 }else{ for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } }
5 try-catch方式处理异常
-
定义格式
try { 可能出现异常的代码; } catch(异常类名 变量名) { 异常的处理代码; }
-
执行流程
- 程序从 try 里面的代码开始执行
- 出现异常,就会跳转到对应的 catch 里面去执行
- 执行完毕之后,程序还可以继续往下执行
-
示例代码
public class ExceptionDemo01 { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); } public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[3]); System.out.println("这里能够访问到吗"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("你访问的数组索引不存在,请回去修改为正确的索引"); } } }
-
注意
如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码如果出现的问题没有被捕获,那么程序如何运行?
那么try...catch就相当于没有写.那么也就是自己没有处理.
默认交给虚拟机处理.同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.
注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
4.8 Throwable成员方法(应用)
-
常用方法
方法名 说明 public String getMessage() 返回此 throwable 的详细消息字符串 public String toString() 返回此可抛出的简短描述 public void printStackTrace() 把异常的错误信息输出在控制台 示例代码
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
// 返回此 throwable 的详细消息字符串
System.out.println(e.getMessage());
// 返回此可抛出的简短描述
System.out.println(e.toString());
//把异常的错误信息输出在控制台
e.printStackTrace();
}
}
9:自定义异常
-
实现步骤
- 定义异常类
- 写继承关系
- 提供空参构造
- 提供带参构造
-
代码实现
异常类
public class AgeOutOfBoundsException extends RuntimeException { public AgeOutOfBoundsException() { } public AgeOutOfBoundsException(String message) { super(message); } }
学生类
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age >= 18 && age <= 25){ this.age = age; }else{ //如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常 throw new AgeOutOfBoundsException("年龄超出了范围"); } } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试类
public class ExceptionDemo12 { public static void main(String[] args) { // 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁, // 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。 Student s = new Student(); Scanner sc = new Scanner(System.in); System.out.println("请输入姓名"); String name = sc.nextLine(); s.setName(name); while(true){ System.out.println("请输入年龄"); String ageStr = sc.nextLine(); try { int age = Integer.parseInt(ageStr); s.setAge(age); break; } catch (NumberFormatException e) { System.out.println("请输入一个整数"); continue; } catch (AgeOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("请输入一个符合范围的年龄"); continue; } /*if(age >= 18 && age <=25){ s.setAge(age); break; }else{ System.out.println("请输入符合要求的年龄"); continue; }*/ } System.out.println(s); } }
10:finally
用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行
。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
- 实例
public class ExcepTest{
public static void main(String args[]){
int a[] = new int[2];
try{
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
finally{
a[0] = 6;
System.out.println("First element value: " +a[0]);
System.out.println("The finally statement is executed");
}
}
}
- 注意
- catch 不能独立于 try 存在。
- 在 try/catch 后面添加 finally 块并非强制性要求的。
- try 代码后不能既没 catch 块也没 finally 块。
- try, catch, finally 块之间不能添加任何代码。
11:try-with-resources
DK7 之后,Java 新增的 try-with-resource 语法糖来打开资源,并且可以在语句执行完毕后确保每个资源都被自动关闭 。
JDK7 之前所有被打开的系统资源,比如流、文件或者 Socket 连接等,都需要被开发者手动关闭,否则将会造成资源泄露。
try (resource declaration) {
// 使用的资源
} catch (ExceptionType e1) {
// 异常块
}
try 用于声明和实例化资源,catch 用于处理关闭资源时可能引发的所有异常。
public class RunoobTest {
public static void main(String[] args) {
String line;
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
}
}
}
我们实例一个 BufferedReader 对象从 test.txt 文件中读取数据。
在 try-with-resources 语句中声明和实例化 BufferedReader 对象,执行完毕后实例资源,不需要考虑 try 语句是正常执行还是抛出异常。
如果发生异常,可以使用 catch 来处理异常。