FiveteenDay_java 异常
1、异常结构
-
异常是以类和对象的形式存在的
-
在java.lang包下
-
Throwable(可抛出的) 分为两个分支:error(不可处理的,一旦发生直接退出jvm),Exception(可处理的)
-
Exception分为两个分支:编译时异常(Exception的直接子类),RuntimeException(运行时异常)
-
编译时异常:是在编写程序时对所出现的异常进行预处理,如果不处理编译器就会报错。又叫做 受检异常,受控异常(CheckException)
-
运行异常:可以预先处理,也可以不管。又叫做 未受检异常 非受控异常(unCheckException)
-
编译时异常与运行时异常都是在运行时发生的,编译阶段异常是不会发生的 两者区别:编译时异常发生概率较高,运行异常发生概率较低
-
异常处理方式: 1、在方法声明的位置上,使用throws关键字,抛给上一级。 2、使用try...catch语句进行异常捕捉。
public static void main(String[] args) {
int a=10;
int b=0;
int c=a/b;//在这里发现b为0,jvm会new一个ArithmeticException异常对象:
// new ArithmeticException("/ by zero");然后抛出异常,打印输出。
System.out.println(c);
2、运行时异常举例
public static void main(String[] args) {
/*
此程序未输出“执行成功”,原因是程序在此处发生了
ArithmeticException异常,底层new了一个ArithmeticException对象
然后抛出了,由于是main方法调用了10/0所以这个异常对象抛给了main方法
main方法没有处理,将这个异常自动抛给了JVM,JVM最终终止程序的执行。
在此处编写时未出现提示,原因是ArithmeticException extends RuntimeException
此异常是运行时异常。不需要预先处理。
*/
System.out.println(10/0);
System.out.println("执行成功!");
}
3、编译时异常
public static void main(String[] args) {
/*
调用dosome的时候会出现报错,原因是
dosome方法抛出了类没找到异常,此异常是编译时异常,main在调用的时候
需要对dosome可能抛出的异常做预处理,如果不做 编译过不去
编译报错:Unhandled exception: java.lang.ClassNotFoundException
未处理的异常...
*/
//dosome();
}
/*
写一个方法dosome抛出ClassNotFoundExceptiony异常(类没找到异常)
因为ClassNotFoundException父类继承Exception 故是编译时异常
*/
public static void dosome() throws ClassNotFoundException{
System.out.println("dosome!");
}
4、异常处理方式
//第一种处理方式:继续上抛 main方法上抛给JVM
/*public static void main(String[] args) throws ClassNotFoundException {
dosome();
}
*/
//第二种处理方式:try...catch...捕捉异常
public static void main(String[] args){
try {
dosome();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void dosome() throws ClassNotFoundException{
System.out.println("dosome!!");
}
5、捕捉异常与抛出异常合用
public static void main(String[] args) {
/*
在main方法中最好使用try...catch..捕捉异常。原因 我们的目的是解决异常而不是中断程序
若使用throws 抛出异常,main方法把异常抛给JVM,JVM会中断程序的执行。
try{
//方法体
}catch(捕捉的异常 异常变量名){
//处理方法
}
*/
try {
m1();
System.out.println("这一行如果m1不出错就执行,否则不执行");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("这一行在捕捉异常后 继续执行");
}
public static void m1() throws FileNotFoundException {
/*
m2抛出FileNotFoundException异常,编译时异常 可采用throws异常来解决
可写 throws FileNotFoundException 或 throws IOException 或
throws Exception 或者捕捉异常try...catch...。
*/
m2();
}
private static void m2() throws FileNotFoundException {
/*
m3抛出FileNotFoundException异常,编译时异常 可采用throws异常或者捕捉异常来解决
*/
m3();
}
private static void m3() throws FileNotFoundException {
/*
FileInputStream对象在源代码里抛出了throws FileNotFoundException异常
FileNotFoundException继承IOException,IOException有又继承了Exception
故它是编译时异常,m3在调用FileInputStream("")方法时,需要对它抛出的FileNotFoundException
异常进行预处理操作,操作方式有上抛与捕捉异常两种
*/
new FileInputStream("");
System.out.println("上面代码出现异常,此行不执行!");
}
6、try...catch...
-
catch后面的括号里可以写精确的异常,也可以写此异常的父类异常
-
catch可以写多个。catch写多个的时候,必须从上到下,从小到大的原则。
public static void main(String[] args) {
try {
//创建输入流
FileInputStream fs= new FileInputStream("D:\\java\\work");
//读文件
fs.read();
System.out.println(10/0);//这个异常属于运行时异常,可处理也可不处理
} catch (FileNotFoundException | ArithmeticException e) {//java8之后可支持这样写多个
System.out.println("文件没找到!或不存在!");
} catch (IOException e) {
System.out.println("读文件出错!");
}
}
7、异常对象的两个重要方法
获取异常简单的信息描述
String msg=exception.getMessage();
打印异常追踪的堆栈信息
exception.printStackTrace();
public static void main(String[] args) {
NullPointerException npe=new NullPointerException("空指针异常asd");
//获取异常描述信息
String msg=npe.getMessage();
System.out.println(msg);//空指针异常asd
//打印异常堆栈信息
//java后台打印异常堆栈追踪信息的时候,采用的是异步线程的方式打印的
npe.printStackTrace();
/*
输出结果:java.lang.NullPointerException: 空指针异常
at FiveteenDay.Exception07.main(Exception07.java:11)
*/
}
8、关于try...catch中的finally
-
在finally中的语句,try...catch..执行完后一定会执行。(finally一定是与try..catch..搭配使用的)
-
finally在什么情况下使用? 多半在关闭输出,输入流的时候使用
public static void main(String[] args) {
FileInputStream f=null;
try {
//创建输入流
f= new FileInputStream("D:\\java\\wor");
/*
若把f.close()写在这一行,如果以上代码出现异常,则不会执行关闭流。
故通常把关闭流写在 finally中。
*/
//f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
System.out.println("我要关闭流!");
//一开始这样写会报错 f.close(),因为在finally中没有f,f在try中是局部变量,故要把f定义为全局变量
//定义为全局变量后会出现空指针异常 故要判断f是否为空
//因为 close() throws IOException 故需要处理异常 try..catch..
if(f!=null) {
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
9、try与finally连用
public static void main(String[] args) {
/*
try和finally可以连用
执行顺序是先执行try...
在执行fianlly...
最后执行return
*/
try{
System.out.println("try....");
return;
}finally{
System.out.println("finally...");
}
}
运行结果:
try.... finally...
try{
System.out.println("try....");
System.exit(0);//这条语句可以不让finally语句执行
}finally{
System.out.println("finally...");
}
运行结果:
try....
特殊情况:
public static void main(String[] args) {
int result=sum();
System.out.println(result);//这个返回值不是11,而是10
/*
原因:java语法规定 自上而下执行方法体(亘古不变)
反编译之后的代码:
public static int sum(){
int i=10;
int j=i;
i++;
return j;
....
*/
}
public static int sum(){
int i=10;
try{
return i;
}finally {
i++;
System.out.println(i);//11
}
}
10、final,finally,finalize 的区别
final:
final修饰的方法不能被覆盖
final修饰的类不能被重写
final修饰的变量值不能改变
finally:
与try联合使用 finally中的程序一定会被执行
finalize:
这个是Object中的方法名 由垃圾回收器GC负责调用
11、自定义异常类
低的话就继承RuntimeException
/*
自定义异常类
有的时候sun公司写的异常类不能够满足程序需求,我们可以自己编写异常类
定义异常类的步骤:
1>编写一个异常类继承Exception或者RuntimeException
2>提供两个构造方法:无参构造与带有String参数的有参构造
*/
//这个是编译时异常
public class MyException extends Exception{
public MyException() {
}
public MyException(String s){
super(s);
}
}
/*这个是运行时异常
public class MyException extends RuntimeException{
public MyException() {
}
public MyException(String s){
super(s);
}
}
*/
浙公网安备 33010602011771号