笔记14
课程内容
1、异常
2、File类
一、异常
1、概述
java程序中,出现不正常的情况,或者错误,称为异常
2、将异常封装成对象,对象中描述不符合正常情况的异常,包含这个情况的原因,类型,描述以及位置
3、异常是可以进行捕获,对这个异常进行处理,不会影响程序后续的执行
package com.ujiuye.dmeos;
import java.util.Scanner;
public class Demo_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int nextInt = sc.nextInt();
System.out.println(8 / nextInt);
System.out.println("hello");
}
}
异常的体系
1、Throwable,异常体系的顶层父类,其他的异常类型或者错误都是Throwable的子类类型,只有Throwable类型体系,才可以使用异常的捕获处理
2、Error:错误,是Throwable的子类,用于描述那些无法捕获和处理的情况,属于特别严重的错误。一旦发生程序不能正常执行
3、Exception: 异常,是Throwable的子类,用于描述那些能够捕获和处理的情况,属于不太严重的错误。即使发生了异常,如果对异常进行捕获,那么程序还是能够正常执行的
4、RuntimeException:运行时异常,是Exception的特殊的子类,在编译阶段不做检查,编译阶段看不出来代码会发生异常
5、体系图
Throwable
Error
Exception
RuntimeException
package com.ujiuye.dmeos;
import java.util.Scanner;
public class Demo_2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int nextInt = sc.nextInt();
try {
System.out.println(8 / nextInt);
} catch (Exception e) {
System.out.println("发生了算数异常");
}
System.out.println("hello");
}
public static void test_1() {
}
public static void test_2() {
}
}
jvm中默认处理异常的机制
1、在程序中的某个位置发生了异常,出现了不正常的情况,在出现不正常情况的位置,将不正常的情况(异常)抛出
2、将异常兑现抛给调用该方法的方法
3、某个方法收到底层方法抛上来异常,如果没有办法处理,继续向上抛,最终抛给主方法,主方法也没有办法处理,抛给调用自己的jvm虚拟机
4、jvm虚拟机处理不了这个异常,就会将此异常的所有信息,通过标准的错误流打印出来,结束jvm虚拟机
5、总结:jvm默认处理的机制【一层一层向上抛,jvm处理不了打印异常信息,终止程序】
package com.ujiuye.dmeos;
public class Demo_3 {
public static void main(String[] args) {
test_1();
}
public static void test_1() {
test_2();
}
public static void test_2() {
test_3();
}
public static void test_3() {
test_4();
}
public static void test_4() {
System.out.println(1 / 0);
}
}
手动处理异常的方式
1、有两大类处理异常的方式
异常的声明:针对编译时异常,某个方法有编译时异常,编译阶段就报错,编译通不过的,需要在方法的声明上对这个编译时异常声明,声明后,编译阶段就能够正常通过了。
异常的处理(捕获):编译时异常,运行时异常都可以进行处理,出现了异常情况,可以通过某种格式完成对异常的捕获和处理,可以让程序在出现异常之后,对异常进行自己处理逻辑,不影响程序后续的执行。
2、捕获处理异常的方式
try...catch
try...catch...finlly
try...finlly不能捕获异常
try…catch
1、格式:
try{
可能发生异常的代码;
}catch(可能出现异常的类型 标识符){
如果发生了异常,对这个异常的处理方式
}
2、说明:
try {},是有可能出现异常的代码,try语句作用就是对可能出现异常情况代码的检测
3、catch:抓住
抓住try语句中检测到的异常,定义处理异常的方式
小括号中声明的可能出现的异常类型,标识符自己给该异常类型起的变量名
大括号中用于定义发生异常之后处理方式:可以打印栈帧的轨迹,可以简单的打印,进行日志的记录,或者就不处理等。
4、运行机制:
(1)运行try语句中的代码
(2)如果没有发生异常,就不会执行catach语句块中的内容
(3)如果try中发生了catch中声明的异常,那就会被捕获到,执行catch中的语句块
即使捕获了,对于try中发生异常代码之后的代码是不能执行了
(4)如果try中发生了异常,但是catch中没有声明这个异常,那么就无法捕获,采用jvm默认处理机制
package com.ujiuye.dmeos;
import java.util.Scanner;
public class Demo_4 {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
int nextInt = sc.nextInt();
System.out.println(8 / nextInt);
System.out.println("还好算数异常没发生,我才能执行");
System.out.println("请输入一个索引值");
int index = sc.nextInt();
int[] arr = new int[3];
System.out.println(arr[index]);
} catch (ArithmeticException a) {
System.out.println("不能进行除0运算");
}
System.out.println("我能正常执行吗");
}
}
try…catch…catch…
1、在一段代码中,可能出现多种异常(虽然一次运行只能出现一个异常,但是每次出现的是哪一个异常是不确定的),所有就要多种处理异常的机制
2、格式:
try{
可能出现异常的代码;
}catch(异常类型1 异常对象名1){
出现异常1的处理情况
}catch(异常类型2 异常对象名2){
出现异常2的处理情况
}....
3、运行流程
(1)执行try中的代码,没有异常,catch中的语句体都不执行
(2)如果有异常,那么就在发生异常的位置,直接跳转到和该异常相匹配的catch块中,执行catch块中的内容,执行完之后,try。。catch就结束了,从上到下依次进行匹配
4、注意:
(1)如果在各个catch块中,出现了子父类的异常类型,那么子类异常的catch块,必须在父类类型catch块的上面,因为catch块是从上到下匹配的,如果父类的catch块在上面,下面的catch块就称为了无法到达的catch块,无法到达的代码
(2)在jdk1.7之后,可以对异常类型进行逻辑的或运算,使用|表示,多种异常情况,可以使用同一种处理方式
catch(异常类型1 | 异常类型2 | 异常类型3 | 异常类型n e){
对这些异常采用相同处理逻辑的代码;
}
package com.ujiuye.dmeos;
import java.util.Scanner;
public class Demo_5 {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
int nextInt = sc.nextInt();
System.out.println(8 / nextInt);
System.out.println("还好算数异常没发生,我才能执行");
System.out.println("请输入一个索引值");
int index = sc.nextInt();
int[] arr = new int[3];
System.out.println(arr[index]);
arr = null;
System.out.println(arr[0]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException | NullPointerException e) {
System.out.println("发生了算术或者数组下标越界或者空指针异常");
}
System.out.println("hello");
}
}
try…catch…finally
1、格式:
try{
可能发生异常的代码;
}catch(可能出现异常的类型 标识符){
如果发生了异常,对这个异常的处理方式
}finlly{
一定要执行的代码;
}
2、finlly:一定要运行的代码
(1)如果把代码发到try中,如果在这行代码的前面发生了异常,这行代码就无法执行
(2)如果将这行代码放到catch中,如果try中没有发生异常,catch中的代码就无法执行了,try中发生异常,这行代码才能执行
(3)finally:也是一个代码块,在这个代码块中,一定会执行,无论我们上面描述的那种情况,finall中的内容都要执行,即使在代码中有return;语句,finall中的内容还是会执行。
(4)作用:一般关闭资源
package com.ujiuye.dmeos;
public class Demo_6 {
public static void main(String[] args) {
try {
System.out.println(1 / 0);
} catch (Exception e) {
System.out.println(" 发生了异常");
return;
} finally {
System.out.println("我是一定要执行的代码");
}
}
}
try…finally
1、格式:
try{
可能发生异常的代码
}finally{
一定要执行的代码
}
2、
(1)无法捕获和处理异常的,一旦发生异常,还是会按照jvm默认处理异常的机制进行处理
(2)无论try中是否发生异常,finally中的语句都是执行
(3)finally中的语句能否执行,取决于代码能够正常执行到try语句块中。
(4)作用:如果有两个代码段,不希望第一个代码段的执行成功与否会影响我们第二个代码段的执行。那就把这两个代码段分别放入try和finlly中
package com.ujiuye.dmeos;
public class Demo_7 {
public static void main(String[] args) {
System.out.println(1 / 0 );
try {
System.out.println(1 / 0);
} finally {
System.out.println("我也是一定会执行的代码");
}
}
}
编译时异常运行时异常
1、编译时异常:在编译阶段就要对此异常进行检测,一旦有了编译时异常,在编译阶段代码的编译时通不过的,只有通过异常的两个处理手段进行解决
异常的声明
异常的捕获
2、运行时异常:在编译阶段不做检查的异常,在编译阶段即使有了运行时异常,也不会编译失败,相当于编译阶段没有异常,可以通过异常的捕获进行解决
3、继承中体系的区别:
运行时异常就是RuntimeException以及RuntimeException下面的子类类型
编译时异常:Exception和Exception下面的子类类型除了RuntimeException
package com.ujiuye.dmeos;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;import com.sun.javafx.animation.TickCalculation;
public class Demo_8 {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.ujiuye.dmeos.Demo_1");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(1 / 0);
}
}
继承体系中常用的方法
1、发现在异常体系中,所有的方法定义在Throwable这个顶层父类中,子类中没有什么特有的方法
2、Throwable中的构造方法
Throwable();构造一个将 null 作为其详细消息的新 throwable。
Throwable(String message) 构造一个将 message 作为其详细消息的新 throwable。
Throwable(Throwable cause) 构造一个有原因的异常对象
Throwable(String message, Throwable cause)
3、常用方法:
getMessage()返回此 throwable 的详细消息字符串
toString()返回异常对象的信息
printStackTrace()打印就是异常调用过程中栈轨迹
getCause()
package com.ujiuye.dmeos;
public class Demo_9 {
public static void main(String[] args) {
Throwable th1 = new Throwable();
System.out.println(th1.getMessage());
System.out.println("th1 " + th1.getCause());
Throwable th2 = new Throwable("这是一个bug");
System.out.println(th2.getMessage());
Throwable th3 = new Throwable(th2);
System.out.println(th3.getMessage());
System.out.println("th3 :" + th3.getCause());
Throwable th4 = new Throwable("我不是bug", th2);
System.out.println(th4.getMessage());
System.out.println("th4:" + th4.getCause());
System.out.println(th4.toString());
test();
}
public static void test() {
Throwable th1 = new Throwable();
th1.printStackTrace();
}
}
throw关键字
1、throw:抛出一个异常对象
2、异常是一个对象,当程序运行到某种情况的时候,认为程序运行的情况和日常生活中的情况不符合,就可以对当前情况的描述封装一个异常对象,通过throw进行抛出
3、作用:
创建一个异常对象,使用throw关键字进行抛出,实现程序的结束或者跳转
4、说明:
如果抛出的是编译时异常,那么这个异常在编译阶段就要进行处理,才能编译成功
如果抛出的是运行时异常,在编译阶段相当于没有异常的,可以不处理这个异常。
package com.ujiuye.dmeos;
public class Demo_10 {
public static void main(String[] args) {
Person p = new Person();
try {
p.setAge(200);
} catch (Exception e) {
System.out.println("年龄不合法");
}
}
}
package com.ujiuye.dmeos;
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
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) throws Exception {
if(age >= 0 && age <= 100) {
this.age = age;
}else {
throw new Exception("年龄不合法");
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}