异常
什么是异常?
异常指程序过程 中的不正常情况
程序执行过程中发生了不正常的情况,这种不正常的情况叫做异常
Java提供了异常的处理方式,出现异常java将会把异常信息打印输出,方便进行修改,让程序更加健壮
int a = 10;
int b = 0;
int c = a/b;
以上程序会出现异常:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at 多态.接口.main.main(interfacsTest1.java:33)
这个信息就是异常信息,由JVM虚拟机打印
异常以类的方式存在
//创建对象
ArithmeticException ae = new ArithmeticException("异常");
//打印异常
System.out.println(ae);
int a =10;
int b=0;
int c =a/b;//JVM在出错的时候将会new异常对象
异常类的继承结构
object类下有Throwable类(可抛出的)
Throwable类有两个分支
1.Error(不可处理,直接退出JVM)
2.Exception(可处理的),
Exception的直接子类:编译时异常(要求在编写程序阶段必须预先处理这些异常,否则编译器报错,因此叫做编译时异常)
RuntimeException:运行时异常( 在编写程序阶段可以作处理,也可以不管)
编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常时不会发生的,为什么叫编译时异常?
在编译阶段需要做预处理,否则编译器报错,因此得名
所有异常都在运行阶段发生的,因为只有运行阶段可以new对象((异常对象)
编译时异常与运行时异常的区别
编译时异常发生概率较高
例:不打伞会生病(生病异常)
但出门前带伞(预处理)可以规避生病
运行时异常发生概率较低
例:走在街上,楼上丢下花盆
100 / 0 (报错:0不能作除数)
概率很低,做预处理会很累
如果不分编译时异常和运行时异常做预处理将会怎样?
:程序会绝对安全,但是很费程序员(编写程序太累,需要作很多预处理)
异常处理方法
1使用throws关键字抛给上一级,谁调用,抛给谁(犯错上报领导)
上抛后调用者同样有两种处理方法,但异常被抛给JVM,将会停止程序
2使用try…catch语句捕获异常,谁也不知道,因为我捕捉了(犯错自己补偿,领导不知道)
要点
-
异常以类的方式存在
-
火灾(异常)
小a家里发生火灾(异常对象)
小b脚力发生火灾(异常对象)
类是 模板
对象是 实例(实际的个体)
throws和try…catch用法
import java.io.FileInputStream;
public class c1 {
public static void main(String[] args) {
c1 c1= new c1();
c1.m1();
}
void m1 (){
System.out.println("m1 start");
m2();
System.out.println("m1 end");
}
void m2 (){
System.out.println("m2 start");
//未预处理异常
new FileInputStream("");
System.out.println("m2 end");
}
}
未处理的异常:java.io.FileNotFoundException异常
因为IO文件流是编译时异常的子类,所以未预处理异常将不允许通过编译
此时可以利用throws抛给调用者
//用FileInputStream 类型抛出
void m3() throws FileInputStream{
System.out.println("m3 start");
//未处理异常
new FileInputStream("");
System.out.println("m3 end");
}
此时m2接受异常,报错原因同样是未处理异常
为所有方法加上throws抛出异常,最后异常到了main方法,若是继续抛出将会抛给JVM,会停止程序
所以在main方法里进行try…catch异常捕获
在try里的代码块报错,将会寻找对应catch里的异常类型,而后执行代码块
注意!
在程序遇到异常后将会停止运行
finally
配合try使用
不管是否遇到异常,都会执行finally代码块里的代码
retun一定是最后执行的
但是退出JVM后,程序直接退出
不会执行finally块
运行结果
拓展
以下代码运行结果是多少?
public static void main(String[] args) {
//打印返回值
System.out.println(trycFinally拓展.m());;
}
static int m(){
int i = 10;
try {
//结果?
return i;
}finally{
i++;
}
为什么?
因为java的语法规则里有这样两条规则:
1.方法体的代码必须遵从自上而下逐次运行
2.retun一旦执行,整个方法必须结束
这两条规则永远不会变
.
finally代码块似乎违背了规则
但是反编译class文件代码是这样的:
static int m(){
int i =10;
int j =i;
j++;
retun j;
}
retun在i=10下,返回的是系统创建的临时变量 j
不影响i++