一、异常
1.1 介绍
即程序中的报错。
java中异常也是一些类,报错出的信息其实是异常类的对象信息。
Java中异常体系:
-
Throwable是所有异常的父类,有两个子类:
- Error
- 表示非常严重的错误问题
- 必须要处理,且是抛出不能捕获(隐藏)
- 例如,堆栈内存溢出
- Exception
- 表示普通异常问题
- 可以抛出也可以捕获,甚至有些异常都不用处理(不明显的)
- Error
1.2 编译期和运行期异常
-
编译期异常是指:编写完代码运行前,会出现的异常
- 编译期异常必须处理(抛出,捕获)
- 编译期异常有哪些:除了RuntimeException及其子类其余都是
-
运行期异常是指:写代码没问题,运行过程中出现的异常
- 运行期异常可以不用主动处理,也可以处理
- 运行期异常是RuntimeException及其子类
1.3 处理异常之抛出
1.3.1 什么是抛出
- 异常抛出就是将错误信息层层向上(方法调用)抛出。最终抛出到main方法,主方法将错误信息抛出到控制台 – 即红色异常信息
1.3.2 怎么抛出的
- 抛出异常分两步:
- 1)代码中使用 throw + 异常对象,来抛出异常
- 其实通过throw主动抛出异常对象并不常用
- 因为有一部分异常抛出的是内部抛出的,我们看不见
- 但是如果以后我们自己想主动抛出,就要这样用
- 2)在方法声明上使用 throws+异常类 来声明要抛出的异常
- 允许同时声明多个异常类名
- 特别注意:方法上声明抛出异常,不一定一定会抛出异常
- 1)代码中使用 throw + 异常对象,来抛出异常
- 抛出异常的作用:
- 如果真有报错,抛出异常信息会在控制台看见
- 一旦真有报错,抛出异常后,错误后面的代码将不再执行
1.3.3 总结
- 当声明抛出的异常过多时,可以使用最大异常涵盖所有
1.4 处理异常之捕获
1.4.1 什么是捕获:
-
抛出异常是:直接将代码报错信息直接抛出,最终抛出到控制台,代码不能运行
-
捕获异常是:将代码报错信息捕获(拦截)后做一些处理,代码还能继续执行
1.4.2 如何捕获异常:
-
使用try -catch代码块包裹可能要报错的代码
-
public static void main(String[] args) { try{//try里面写的是感觉要报错的代码 System.out.println(1); System.out.println(2/0); }catch (Exception ae){//准备要捕获异常类型 //catch内写的是,抓住之后要做的事情 //发短信,记录日志 System.out.println("4" + ae); } System.out.println(5);//一定会执行 }
1.4.3 执行顺序:
- try之前正常执行
- try内如果没报错,try内正常执行,catch内不执行
- try内如果有报错,从报错处后面不执行,catch就会执行
- 无论try-catch是否有报错,try-catch后的代码一定会执行
1.5 处理异常的区别
- 抛出异常
- 抛出异常后,后续代码不能执行
- 抛出给调用者,调用者也需要处理异常
- 捕获异常
- 捕获异常后,后续代码还能执行
- 自己捕获的异常,后续别人调用该方法,就不需要处理异常
1.5 重写中的异常
- 第一版(继承):子类方法与父类方法 访问修饰符 返回值类型 方法名(参数) 完全一样
- 第二版(访问修饰符后):
- 子类方法访问修饰符 大于等于 父类方法修饰符
- 第三版(异常):
- 子类方法抛出异常范围 小于等于 父类
- 特别的,父类方法没有异常,子类方法重写时不能抛出异常,如果有异常只能捕获
1.6 异常API
异常类的一些方法
- 有参构造
- printStackTrace() 打印异常信息
- getMessage() 获得异常信息
- toString() 将异常信息转为字符串
这些方法在捕获异常内写:
public static void main(String[] args) {
try{
System.out.println(1/0 );
}catch (Exception e){
String message = e.getMessage( );
System.out.println("message ==>" + message );
String string = e.toString( );
System.out.println("string ==>" + string );
System.out.println("----------------" );
e.printStackTrace();// 将错误信息打印到控制台
}
}
1.7 特殊的写法:finally
写法:
//写法1:
try{
//...
}catch(Exception e){
//...
} finally{
// ...
}
//---------------------
// 写法2
try{
}finally{
// ...
}
什么作用?
- 语法: 无论try内是否有报错,finally一定会在最后执行
- 即finally内的代码无论如何都会执行
- 放在最后,用于关闭"通道" , 释放资源
public static void main(String[] args) {
// try{
// System.out.println(1/0 );
// }catch (ArrayIndexOutOfBoundsException e){
// System.out.println(e );
// }finally {
// System.out.println("最终执行的...." );
// }
try{
System.out.println(1/0);
}finally {
System.out.println("最终执行的...." );
}
}
1.8 自定义异常
实现步骤:
- 自定义类
- 继承Throwable体系下任何异常类都行
- 但是要注意: 继承哪种就有哪种异常特性
- 比如: 继承编译期异常,我们自定义异常也必须要必须处理
- 继承运行时异常,我们自定义异常就不用处理
- 有参构造,传递异常信息
- 在某些方法中通过throw + 异常对象抛出异常
//自定义异常类
public class AgeOutOfBoundsException extends Exception{
public AgeOutOfBoundsException(int age){
super(String.valueOf(age));
}
}
//类中使用异常
public class Student {
private int age;
public int getAge() {
return age;
}
// throws 声明抛出异常
public void setAge(int age) throws AgeOutOfBoundsException {
if (age >= 0 && age <= 120) {
this.age = age;
}else{
// throw是真正抛出异常对象
throw new AgeOutOfBoundsException(-1);
}
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
'}';
}
}
//测试
public static void main(String[] args) throws AgeOutOfBoundsException {
Student s = new Student( );
s.setAge(-1);
System.out.println(s );
}
1.9 总结
关于异常其实很简单: 顺其自然
就是写完代码提示你报错,那就捕获或者抛出,没提示就不用管,继续写代码就行
只不过是看公司或者项目要求是选择抛出还是捕获
但是要分得清: 抛出和捕获的区别
其他的比如: 重写中的异常,异常api,finally等都是随着代码积累,慢慢见到认识
new Student( );
s.setAge(-1);
System.out.println(s );
}