一、异常的概念
代码运行过程中出现的问题
异常也是对象
有对象就有类
二、异常的分类
三、异常的产生
异常是对象,有对应的类型
通过代码在指定位置创建一个异常对象,然后**“抛出”**
1、运行时异常的产生
案例
package com.qjzx._03_exception;
public class Student {
private String name;
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 上网:如果年龄不足18岁,则发生异常,创建异常对象并使用throw关键字抛出
*/
public void viewIntel() {
if(this.age >= 18) {
System.out.println("上网真好耍!");
}else {
//异常!
//创建异常对象并“抛出”
throw new RuntimeException("你还未成年呢!");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2、异常的处理
(1)try…catch
package com.qjzx._03_runtimeexception;
public class StudentTest {
public static void main(String[] args) {
/*
*
* try{
*
//可能产生异常的代码
}catch(捕获的异常类型 e){//e是形式参数
//该异常捕获之后要做的操作
}catch(捕获的异常类型 e){//e是形式参数
//该异常捕获之后要做的操作
}finally{
//异常发生之后一定会执行到的语句块:①流资源关闭②释放锁
}
*
*
* */
Student st = new Student("张三",16);
try {
st.viewIntel();//RuntimeException 感冒
System.out.println(123);
}catch(IndexOutOfBoundsException e) {//流鼻涕
//捕获到了如何处理
//控制台打印栈的跟踪信息
//从异常对象的产生 -- 传播记录
System.out.println("IndexOutOfBoundsException");//抓点药
e.printStackTrace();
}catch(RuntimeException e) {//感冒
System.out.println("RuntimeException");//打针
e.printStackTrace();
}catch (Exception e) {//生病
System.out.println("Exception");//动手术
e.printStackTrace();
}
System.out.println(456);
}
}
异常的简单处理:
异常的大小类型:
异常的捕获顺序:
(2)异常的传播
异常可以向上传播
运行时异常如果没有处理,自动向上传播
编译异常需要在方法签名处通过throws关键字声明传播的异常类型
3、编译异常的产生
package com.qjzx._04_exception;
import java.rmi.NotBoundException;
public class Student {
private String name;
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 上网 一个方法同时只能抛出一个异常对象
*/
public void viewIntel() throws IllegalAccessException, NotBoundException{
if(age <= 0) {
throw new IllegalAccessException("你家年龄有负数吗");
}else if(this.age >= 18) {
System.out.println("上网真好耍!");
}else {
//异常!
//创建异常对象并“抛出”
throw new NotBoundException("你还未成年呢!");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4、编译异常的处理
(1)try…catch
package com.qjzx._04_exception;
import java.rmi.NotBoundException;
public class StudentTest {
public static void main(String[] args) {
Student st = new Student("王五",-1);
try {
st.viewIntel();
//catch如果同时捕获多个类型,这多个异常类型不能有继承关系
} catch (IllegalAccessException | NotBoundException | RuntimeException e) {
e.printStackTrace();
}
System.out.println(456);
}
}
(2)throws 向上传播/抛出
public class StudentTest {
public static void main(String[] args) throws IllegalAccessException, NotBoundException {
Student st = new Student("王五",-1);
st.viewIntel();
System.out.println(456);
}
}
四、finally关键字
1、语法
finally用在try…catch语句块中,表示最终会执行的代码
finally语句之前,如果有执行退出虚拟机,也是不会执行finally语句块
无论是否产生异常,finally一定会执行
public class StudentTest {
public static void main(String[] args) {
Student st = new Student("赵六",14);
try {
st.viewIntel();
//上一句代码可能会抛出异常,也可能不会
//如果抛出了,则这句代码肯定不会执行到
//有些情况下,我们要求,即使抛出了异常,这句代码也必须执行到
// System.out.println("123");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
} finally {
System.out.println("123");
}
System.out.println("456");
}
}
设计到资源的释放,链接的关闭这些,和异常捕获一起来用的时候,要放入到finally语句块中
2、异常处理的语句执行顺序
return和finally
package com.qjzx._05_finally;
import java.rmi.NotBoundException;
public class StudentTest {
public static void main(String[] args) {
System.out.println(test());
}
/**
* return 和 finally谁先执行
* 执行的return语句 是在 finally 的 上方 还是 下面
* @return
*/
public static int test() {
Student st = new Student("赵六",14);
int i = 20;
try {
st.viewIntel();
//上一句代码可能会抛出异常,也可能不会
//如果抛出了,则这句代码肯定不会执行到
//有些情况下,我们要求,即使抛出了异常,这句代码也必须执行到
// System.out.println("123");
return i;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
} finally {
System.out.println("这个是执行了的"+(++i));
}
return i;
}
}
return会终止方法的继续执行
throw也会终止方法的执行
方法有结果:
- 有值返回
- 有异常抛出
五、关于异常常见问题
1、finally和final的区别
没有可比性
final 可选修饰符
类:类为最终类,不能被继承
变量:常量,值不能更改
方法:最终方法,不能被重写
finally:
用在try…catch语句块中,表示一定会执行的代码块
2、throw和throws的区别
throw关键字用在方法体中,用来抛出异常对象
throws用在方法签名中,表示这个方法抛出的异常类型
3、return和finally的执行顺序
//这种写法是没问题的
try {
}finally {
}
六、自定义异常
如果java中提供的异常类型不符合我们的使用场景,我们也可以自定义异常类型
自定义异常
-
运行时异常
继承RuntimeException
-
编译异常
继承Exception
/**
* 自定义一个运行时异常:年龄不合法异常
* @author Administrator
*
*/
public class AgeNotAccessException extends RuntimeException{
public AgeNotAccessException(String message) {
super(message);
}
}
/**
* 编译异常:未成年异常
* @author Administrator
*
*/
public class NotYetOfAgeException extends Exception{
public NotYetOfAgeException(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 void viewIntel() throws NotYetOfAgeException{
if(age <= 0) {
throw new AgeNotAccessException("年龄不合法!");
}else if(this.age >= 18) {
System.out.println("上网真好耍!");
}else {
//异常!
//创建异常对象并“抛出”
throw new NotYetOfAgeException("你还未成年呢!");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class StudentTest {
public static void main(String[] args) {
//运行时异常都会通过合理的代码逻辑进行规避
//运行时异常不需要捕获和处理的
int age = -1;
if(age <= 0) {
age = 18;
}
Student st = new Student("王八",age);
try {
st.viewIntel();
} catch (NotYetOfAgeException e) {
e.printStackTrace();
}
System.out.println(123);
}
}
Name(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class StudentTest {
public static void main(String[] args) {
//运行时异常都会通过合理的代码逻辑进行规避
//运行时异常不需要捕获和处理的
int age = -1;
if(age <= 0) {
age = 18;
}
Student st = new Student("王八",age);
try {
st.viewIntel();
} catch (NotYetOfAgeException e) {
e.printStackTrace();
}
System.out.println(123);
}
}