JAVA异常 try..catch方法 throw和throws 自定义异常
异常 try…catch方法 throw和throws 自定义异常
这部分的笔记几乎是没做任何整理,直接把课上的笔记和教材照搬进来,可做的练习也很少。只要会try…catch方法,明白异常和异常抛出是个怎么回事就行…
异常
在java程序,出现了不正常或错误的情况,称为异常
异常就是一个对象,描述一些不正常的情况信息:异常的原因,位置,类型
异常也是一种处理机制,我们可以对异常进行捕获处理,或者结束程序
出现了错误,必须修改源代码,出现了异常,可以捕获
异常的体系
-
Throwable: 可以抛出,是异常体系的顶层父类,其他的错误或异常,都是他的子类,只有Throwable体系下的类,才可以使用异常的处理机制来处理
-
Error:错误,用于描述那些无法捕获和处理的错误信息
-
Exception:异常,用于描述那些可以捕获和处理的错误信息
-
RuntimeException:运行时异常,这种异常在编译的时候不会检测,能够正常通过,只有出现相对应的问题的时候,才会被抛出
-
编译时异常:除了RuntimeException之外都是编译异常,编译时有异常编译就不能通过,必须要对编译异常进行处理
Jvm默认异常的处理机制
-
如果出现了不正常的情况,jvm就把其封装为异常对象,同时再抛出,抛出给代码的调用者
-
方法执行的时候,如果其他方法产生了异常,在执行的时如果没有手动处理,就会把这个问题抛给方法的调用者,调用者也没处理的话jvm就把这个异常抛出,用红色信息显示
总结:jvm默认处理的方式:一层层向上抛出,最后到达jvm,jvm将异常信息打印出来,同时结束程序
手动处理异常的方式
目的:就是为了当程序出现问题,也能让程序继续执行下去,不至于立即结束程序
手动处理异常的分类:
(1) 异常的声明式处理
- 当某个方法有编译异常的时候,可以通过声明式处理,即在调用有编译时异常的方法名之后+throws关键字,抛出即可
(2) 异常的捕获式处理
- 出现异常时,可以通过某种格式,将异常捕获,从而实现程序的整除执行
异常的捕获方式分类:
(1) try…catch
(2) try…catch…finally
(3) try… finally(此方式不能捕获异常)
try…catch
格式:
try{
可能出现问题的代码
}catch( 异常的类型 变量名){
处理异常的代码
}
try:尝试执行try后大括号中的代码
catch :如果try后的大括号中有问题产生,就可通过catch捕获
小括号中声明可能出现的异常类型,变量名,就是一个引用,指向了将来出现的异常对象
执行流程:
-
先执行try后的大括号中的代码,如没问题,就跳过trycatch语句,继续执行后面的代码
-
如果产生了问题,就用catch进行异常的捕获,并把异常对象赋值给变量名,catch中写上异常的处理方式,方式:记录日志,打印错误信息,或者重新执行try后的代码最简单的方式,鸵鸟政策,或者自己将异常抛出
-
catch后的代码块如果执行完,就可以执行catch大括号后的代码
-
如果发现了catch没有声明的异常,则无法捕获异常,该异常就使用jvm默认的方式来处理
package Test;
public class Test {
public static void main(String[] args) {
String s = null; //空指针异常,是异常就可以进行
try {
//可能发生问题的代码
System.out.println(s.length());
} catch (Exception e) {
//出现了能够捕获的异常
System.out.println("空指针异常了");
}
System.out.println("我还能继续进行");
}
}
try…catch…catch…catch
可能出现多个异常,需要准备多种处理方式,准备多个catch块
格式
try{
可能出现异常的代码
}catch(异常类型1 变量名1){
异常处理方式1
}catch(异常类型2 变量名2){
异常的处理方式2
}catch(异常类型3 变量名3){
异常的处理方式3
}
执行流程
-
如果try后的代码没问题,就直接结束整个catch块
-
如果出现了问题 jvm把问题封装为一个异常对象,查看这个异常度下行的类型,哪个catch后的异常类型和该类型一致,就执行哪个异常处理方式,执行完就 结束整个catch块,继续执行其他代码
注意:
- 异常是有继承关系,不能先捕获父类类型,否则就报错,应该先捕获子类类型异常,再捕获父类类型异常,因为父类类型异常包含了子类,子类异常无法到达,系统认为你写的是多余的,就会报错
- 把父类异常写在最下面
jdk1.7新的捕获异常处理方式
try{
有问题的代码
}catch(异常类型1 | 异常类型2 | 异常类型3 |… 变量名){
多种异常处理方式是一样的
}
package Test;
public class Test {
public static void main(String[] args) {
int[] arr = {
1,2,3};
arr = null;
try {
System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
//此时两个异常共用一个处理方式
System.out.println("傻子你咋操作的数组");
}
System.out.println("~~~~~~~~~~~~");
test();
}
private static void test() {
int[] arr = {
1,2,3};
//arr = null;
try {
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组索引越界,请检查下标");
} catch (NullPointerException e) {
System.out.println("你操作的数组为null,请给对象赋值");
} catch (RuntimeException e) {
//大范围的异常一定要放在小范围的异常下面
// TODO: handle exception
}
System.out.println("我总能执行");
}
}
try…catch…finally
格式
try{
可能出现问题的代码
}catch(异常类型 变量名){
异常的处理方式
}finally{
一定会执行的代码
}
finally :最终的,一定会执行的代码
执行流程:
-
try后的代码如果没有问题,就执行finally中的内容
-
如果有问题先执行catch,再执行finally
-
无论有没有异常出现,都会执行finally的代码块
-
用途:释放资源
package Test;
public class Test {
public static void main(String[] args) {
int[] arr = {
1,2,3};
try {
System.out.println(arr[2]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界了");
} finally {
System.out.println("一定会执行");
}
System.out.println("异常处理后,也能执行");
}
}
try… finally
try{
可能出现问题的代码
}finally{
一定要执行的代码
}
执行流程:
-
无法捕获异常
-
try后如果没有问题,就会执行finally,程序继续执行后面的内容
-
try后如果有问题,也会执行finally,执行之后程序停止
package Test;
public class Test {
public static void main(String[] args) {
String s = "abc";
try {
s.substring(1,4);
}finally {
System.out.println("一定要执行的代码");
}
System.out.println("我可能会执行");
}
}
编译时异常和运行时异常
相同点:无论是编译时异常还是运行时异常,都是运行代码的阶段才可能发生
区别:
(1) 继承体系
-
运行时异常都继承自:RuntimeException
-
编译时异常都继承自:Exception下除了RuntimeException之外
(2) 是否要处理的区别
-
运行时异常,可以选择处理,也可以不处理
-
编译时异常,如果产生编译时异常,必须要进行处理,否则程序无法运行
异常体系中常用的方法
除了Throwable下定义的方法,子类都没有什么特殊的方法,所以只需要研究Throwable中的方法
构造方法:
(1) Throwable()
(2) Throwable(String message) 指定异常信息的构造方法
(3) Throwable(Throwable cause) 创建异常原因对象的构造方法
常用方法:
(1) getCause():获取异常原因对象,有的话返回cause 没有返回null
(2) getMessage: 获取异常信息
(3) toString() 把异常对象转为字符串
(4) printStackTrace(): 打印产出异常的轨迹
package Test;
public class Test {
public static void main(String[] args) {
int[] ages = {
18,29,22};
try {
System.out.println(ages[10]);
} catch (Exception e) {
String message = e.getMessage();
System.out.println(message);//获取异常信息
System.out.println(e.toString());//把异常对象转为字符串
System.out.println(e.getCause());//获取异常原因对象
e.printStackTrace();//打印异常轨迹
}
}
}
throw关键字
作用:把异常对象给抛出
异常是一个独享,当程序执行的时候,发生了问题,就可将异常情况给抛出,抛给调用者,想要解决扔这个问题,就需要使用throw关键字
作用:创建一个异常对象,使用throw抛出,实现程序结束或者跳转
throw抛出异常分类
(1) 如果抛出的是运行时异常,那么可以选择处理,也可以不处理,相当于没有异常一样
(2) 如果抛出的是编译时异常,必须对类型的异常进行处理,否则无法编译通过
throws关键字
抛出:用于声明一个异常类型
在某个方法中,如果有一些编译时异常,要被抛出,方法内部不想处理,就可通过关键字throws把这个异常声明在方法的后面
声明的好处:
- 方法调用者用这个方法的时候,会知道这个方法中可能产生的问题,方法的调用者就可以针对这些问题进行处理
声明异常的格式
-
修饰 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2 …{
可能有异常的代码
}
-
声明异常的分类:
(1) 如果声明的是一个运行时异常,那么声明不生命没有任何区别,所以没有必要声明运行时异常
(2) 如果声明的是一个编译时异常,那么在一个方法调用含有编译时异常的方法,必须对带有声明异常的方法进行处理,处理的方式,捕获式处理和 声明式处理
注意事项
- 如果一个方法同时在throws后声明了多个编译时异常,那么可以直接使用exception替换掉,如果声明的异常包含了父子类关系,不会报语法错误
throw和throws
-
throw用于抛出一个异常对象,throws声明一个异常类型
-
throw是对象实实在在抛出了,一旦使用了throw就一定有一个对象抛出,throws是对可能出现异常的类型的声明,声明了一个异常类型,在这个方法中,也可以不出现任何一场
-
throw出现在方法中,throws出现在方法参数后的小括号后
自定义异常
jdk提供了很多异常类型,但是大多数没有自己的特有的方法
如果有了很多异常类型的名字,将来在不同的异常情况下,就可以使用不同的异常类型去创建对象,可以通过类名去区分到底出现了什么异常
在自己的业务中,jdk提供的各种情况,都无法描述当前的情况,就需要自己定义异常类型,用于自己的项目中
自定义异常的步骤
(1) 定义一个类,以Exception结尾,例如 AgeException,表示一个非法年龄异常
(2) 让自己定义的类去继承一个Exception或者RuntimeException
-
如果定义的是编译时异常,就是Exception
-
如果是运行时异常,就使用RuntimeException
-
构造方法需要手动添加的
package Test;
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setAge(-18);
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
AgeException a = new AgeException("年龄非法");
if(age < 0) {
throw a;
}
this.age = age;
}
@Override
public String toString() {
return "Stundent [name=" + name + ", age=" + age + "]";
}
}
class AgeException extends RuntimeException{
public AgeException() {
super();
// TODO Auto-generated constructor stub
}
public AgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public AgeException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public AgeException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public AgeException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
作者:不要再比了
来源链接:https://blog.csdn.net/ajun4/article/details/107371581
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。