我们通常称一个人不正常的时候说你有病啊,从大的范围来讲病主要有两种病,一种不可治疗,如艾滋、晚期癌症,另一种可治疗,这种可治疗的病又分成两类,一种如小感冒的不需要去医院处理,另一种如阑尾炎必须去医院处理,程序中也有这种不正常的情况,
异常体系.png
比如执行
System.out.println(args[0]);
会报异常
···
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at com.neusoft.test.Test.main(Test.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
如果把args指向null,就会报如下异常
Exception in thread "main" java.lang.NullPointerException
at com.neusoft.test.Test.main(Test.java:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
这些不正常的情况,统称为异常,JAVA是面向对象的语言,任何事物都可以用类来表述,我们就用各种类来表述异常,成为异常类,很多异常类堆积起来,就形成JAVA异常体系,任何异常类错误类都有一个父类叫Throwable,先来看一下Throwable常用方法
toString()返回完整类名+病信息
Throwable t = new Throwable();
String s = t.toString();
System.out.println(t);
getMessage()返回创建Throwable对象传入的信息
Throwable t = new Throwable();
String s = t.getMessage();
System.out.println(s);
会发现,输出null,此时需要指定信息
Throwable t = new Throwable("懒癌");
String s = t.getMessage();
System.out.println(s);
printStackTrace()打印异常的栈信息
举个例子,比方说看病
image.png
看肺炎,医生会一直问到底你的病的原因,肺炎的原因就是因为没盖被
public static void test(){
Throwable t = new Throwable();
t.printStackTrace();
}
test();
java.lang.Throwable
at com.neusoft.test.Test.test(Test.java:14)
at com.neusoft.test.Test.main(Test.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
现在,让我们来看一看Throwable的子类
error错误
演示 字节码文件名不对就要解释,就会发生错误
image.png
Error是jvm或硬件出现的错误,一般不用编写代码去处理
Exception是需要代码去进行处理
如何区分错误与异常
如果程序出现不正常的信息的类名是以Error结束,肯定是错误,如果是以Exception结束,肯定是异常
异常
public static void test(int a,int b){
int c = a/b;
System.out.println(c);
}
test(2,0);
JAVA虚拟机运行到1/0的时候,马上创建一个异常对象,并调用异常对象的printStackTrace()方法
那,出了问题总得要解决,现在就来学习异常处理的方式
捕获处理
try{
}catch(Exception e){
e.printStackTrace();
}
int c = 0;
try {
c = a/b;
System.out.println("哈哈哈");
int[] arr = null;
System.out.println(arr.length);
}catch(ArthmeticException e){
System.out.println(e.toString());
}catch(NullPointerException e){
System.out.println(e.toString());
}
System.out.println(c);
int c = 0;
try {
c = a/b;
System.out.println("哈哈哈");
int[] arr = null;
System.out.println(arr.length);
}catch(Exception e){
System.out.println(e.toString());
}catch(ArthmeticException e){
System.out.println(e.toString());
}catch(NullPointerException e){
System.out.println(e.toString());
}
System.out.println(c);
捕获异常要注意的细节
1、try块中的异常经过处理,try块后的代码可以正常执行
2、如果try块中出现了异常的代码,那么try块中异常代码之后的代码就不会执行
3、一个try块后面是可以跟多个catch块,也就是一个try块可以捕获多种类型异常
4、一个try块可以捕获多种类型的异常,但是异常的类型必须从小到大进行捕获,否则编译报错
疑问1:捕捕获异常打印感觉没多大用
异常处理非常有用,只不过我们目前接触到的非常有限度,举例:项目中跳到错误页面,就用到异常处理
疑问2:以后捕获异常就弄一个Exception就够
开发中会遇到不同的异常类型,因此就需要不同的异常处理方式
抛出处理
抛出处理要注意的细节
1、如果一个方法内部抛出了异常,那么必须要在方法上声明抛出,就像住酒店可能会着火,所以提示,就像温馨提示
2、如果调用一个声明抛出异常的方法,那调用者必须处理
3、如果一个方法内部抛出一个异常对象,那么throw语句后面的代码都不会执行,该方法马上停止
4、在一种情况下,一次只能抛出一种异常对象
public static void test(int a,int b) throws Exception{
if(b == 0){
throw new Exception();
}
int c = a/b;
System.out.println(c);
}
public static void test(int a,int b,int[] arr) throws Exception{
if(b == 0||arr == null){
throw new Exception();
throw new NullPoiterException();
}
int c = a/b;
System.out.println(c);
}
throw和throws
1、throw关键字是用于方法内部,throws关键字是用于方法声明
2、throw关键字是用于方法内部抛出一个异常对象,throws关键字是用于方法声明抛出异常类型
3、throw关键字后只能跟一个异常对象,throws关键字一次可以跟多个异常类型
疑问:抛出处理在何时使用
如果你要通知到调用者,可以抛
如果代码直接跟用户打交道,千万不要再抛,抛的话就给了用户,应该使用捕获异常
自定义异常类
sun给我们提供了很多异常类,用于表述异常,但还不足以表述所有异常,因此需要自定义,比如去购物,没带钱,那就是没带钱异常
需求,模拟fq上线,如果没有插上网线,抛出没有插上网线异常,如果插上网线,就显示好友列表
自定义异常类步骤
自定义一个类继承Exception
需求,模拟你去吃饭,只带10元,不够的情况下的异常
运行时异常与编译时异常
如果方法上声明了一个运行时异常,那么在方法上可以声明也可以不声明,调用者可以处理也可以不处理,如果一个方法内部抛出了一个编译时异常对象,那么方法上就必须要声明,调用者也必须处理
RunTimeException及其子类都是运行时异常
除了运行时异常就是编译时异常
异常的类型不用记
疑问:为什么jvm会如此严格要求编译时异常,对运行时异常如此宽松
运行时异常都是好的编程习惯能避免,因此就没有严格要求运行时异常
编译时异常是编写代码没法避免,比如读写文件,就有IOException,读硬盘数据硬盘坏掉,没法用代码规避
finally块
资源文件使用完一定要解除占用,别的程序无法对该文件进行操作
使用finally的前提一定要使用try块
public static void test(int a,int b) throws Exception{
try {
if (b == 0) {
return;
}
}catch(Exception e){
e.printStackTrace();
}finally {
System.out.println("执行fianally块");
}
}
return、throw等停止的方法都不会阻止finanlly,只有当调用System.exit()方法时才能停掉
finally块非常适合用来释放资源,用finally块也肯定能释放资源
try块的3种组合方式
try{
}catch(){
}
try{
}catch(){
}finally{
}
try{
}finally{
}
其中,最后一种适合运行时异常
网友评论