Java异常处理,try-catch

时间:2023-02-19 15:45:05

一  为什么要有异常处理机制

程序在执行过程中可能会出现一些错误,导致该程序卡死或者一直停留在此处,无法继续运行该程序。这就需要我们处理这些错误。 早期的语言把这些种错误看成是约定俗称的东西,有很多处理错误的方式解决此问题,但它不属于语言的一部分。这就导致不一定每个程序员都会去处理这些错误,为了使程序在出现错误时,程序员必须去解决它,就引入了异常处理机制,不解决没法继续执行

二  Java中的异常处理机制

程序产生异常时,首先在堆上nwe一个异常对象,然后终止当前的执行路径,并在当前环境中弹出对异常对象的引用。
这时候,异常处理机制接管程序,它的作用是将程序从错误中恢复。决定程序继续运行下去,还是以其它路径执行。

三 Java中是怎么处理异常的

1.Throwable类

Java中异常都是通过Throwable类或者其子类来解决的,Throwable的直接子类有两个,一个是Error,另一个是Exception

所以Java中的异常可以分为两种

Error:表示编译时和系统错误,这种不用我们去处理。
Exception:可以被抛出的,也就是我们可以通过代码去解决的。所以主要是学习Exception

结构图如下:
Java异常处理,try-catch


Throwable类的主要方法有三个
 getMessage()         此 Throwable 实例(可以为 null)的详细消息字符串。其实就是说明该异常是什么样的
 printStackTrace()   将此 throwable 及其追踪输出至标准错误流。 就是把产生异常的堆栈跟踪信息打印出来
 toString()                 返回类名+Message信息

getMessage()和toString的代码如下:
public class TestException {
public static void main(String[] args) {
//不传参数,则表示对该异常没有描述,getMessage()打印出为null
Throwable throwable=new Throwable("空指针异常");
System.out.println("toString信息:"+throwable.toString());
System.out.println("toString信息:"+throwable.getMessage());
}
}
打印结果:
toString信息:java.lang.Throwable: 空指针异常
toString信息:空指针异常

printStackTrace()代码:
public class TestException {
public static void main(String[] args) {
test();
}
public static void test(){
Throwable throwable=new Throwable("空指针异常");
throwable.printStackTrace();
}
}



打印结果:
java.lang.Throwable: 空指针异常
at testexception.TestException.test(TestException.java:7)
at testexception.TestException.main(TestException.java:4)
从上面可以看到,printStackTrace()方法会把产生异常的地方压入到一个栈,在向上追溯,直到找到源头,然后全部打印出来。

2.Java中的异常处理方式

Java中的异常处理方式有两种,一种是自己进行处理,另一种抛给其它程序处理

a.自行处理

Java中使用try-catch块进行处理,语法如下: try{ 可能出现异常的代码              注意:try块中有语句出现异常后,该语句后面的语句(try中的语句)都不会执行,因为程序跳到了catch块. }catch(异常类型  变量){ }
看下列例子,如果不处理异常会出现什么
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
a=b/c;
System.out.println(a);
}
}

打印结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at testexception.TestException.main(TestException.java:7)

可以看到产生了异常,程序没有继续执行。
使用try-catch块处理后
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
try{
a=b/c;
}catch(ArithmeticException e){
System.out.println("除数为0");
}
System.out.println(a);
}
打印结果:
除数为0
0

可以看到当我们处理异常后,程序就会继续执行,并且会给出异常信息
多个异常
一个程序中有可能会出现多个异常,怎么处理了 下面一个除数为0异常,一个空指针异常
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
int[] array=null;
try{
a=b/c;
System.out.println(array.length);
}catch(ArithmeticException e){
e.printStackTrace();
}
System.out.println(a);
}
}
打印结果:
java.lang.ArithmeticException: / by zero
at testexception.TestException.main(TestException.java:9)
0

从结果来看,没出现空指针异常,是否是该程序没有空指针异常了,不是,是在处理除数为0异常的时候,直接跳到catch块中, System.out.println(array.length);这句没有执行。把此句放在前面就会出现
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
int[] array=null;
try{
System.out.println(array.length);
a=b/c;
}catch(ArithmeticException e){
e.printStackTrace();
}
System.out.println(a);
}
}
打印结果:
Exception in thread "main" java.lang.NullPointerException
at testexception.TestException.main(TestException.java:9)
报出了异常,没有处理
怎么处理了 其实和单个异常的一样,再加一个相匹配的catch块。在执行的时候,如果出现异常,会从第一个catch块寻找,直到找到相匹配的catch块,处理该异常。
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
int[] array=null;
try{
System.out.println(array.length);
//因为上句有异常抛出,所以下面的异常不再产生
a=b/c;
}catch(ArithmeticException e){
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}
System.out.println(a);
}
}

打印结果:
java.lang.NullPointerException
at testexception.TestException.main(TestException.java:9)
0

也可以直接在catch块使用其父类Exception,这样只写一个catch块就可以解决问题。
package testexception;
public class TestException {
public static void main(String[] args) {
int a=0;
//除数为0会出现异常
int b=6,c=0;
int[] array=null;
try{
System.out.println(array.length);
//因为上句有异常抛出,所以下面的异常不再产生
a=b/c;
}catch(Exception e){
e.printStackTrace();
}
System.out.println(a);
}
}
打印结果:
java.lang.NullPointerException
at testexception.TestException.main(TestException.java:9)
0

如果异常处理的catch块有exception的,也有其子类,那么必须把Exception放在最后一个。因为Exception可以处理所有子类的异常,放在前面,那么后面的catch块不会执行到,程序会报错。
finally关键字    finally关键字就是不管程序有没发生异常(除非jvm退出,即执行System.exit(1)),都会去执行该块中的代码。一般用于释放资源    finally使用之前必须有try块
下面代码发生使用finally,即使发生异常,也会执行finally快中的代码。
package testexception;

import java.util.concurrent.TimeoutException;

public class Test {
public static int a=0;
public static void main(String[] args)throws TimeoutException{
// TODO Auto-generated method stub
a=test(4,0);
}
public static int test(int b,int c){
int a=0;
try{
a= b/c;
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("执行了finally");
}
return a;
}
}

打印结果:
java.lang.ArithmeticException: / by zero
at testexception.Test.test(Test.java:14)
at testexception.Test.main(Test.java:9)
执行了finally


try-catch finally可以组合成三种

第一种 要处理异常,不是释放资源
try{
异常代码块
}catch(异常类型 变量){
处理异常
}

第二种 要处理异常,要释放资源

try{
异常代码块
}catch(异常类型 变量){
处理异常
}finally{
释放资源
}


第三种 抛出的是运行时异常,要释放资源

try{
}finally{
释放资源
}