一、异常简介

什么是异常?

异常就是有异于常态,和正常情况不一样,有错误出错。在java中,阻止当前方法或作用域的情况,称之为异常。

java中异常的体系是怎么样的呢?

Java中的所有不正常类都继承于Throwable类。Throwable主要包括两个大类,一个是Error类,另一个是Exception类;

其中Error类中包括虚拟机错误和线程死锁,一旦Error出现了,程序就彻底的挂了,被称为程序终结者

.Exception类,也就是通常所说的“异常”。主要指编码、环境、用户操作输入出现问题,Exception主要包括两大类,非检查异常(RuntimeException)和检查异常(其他的一些异常)
RuntimeException异常主要包括以下四种异常:空指针异常、数组下标越界异常、类型转换异常、算术异常。RuntimeException异常会由java虚拟机自动抛出并自动捕获(就算我们没写异常捕获语句运行时也会抛出错误!!),此类异常的出现绝大数情况是代码本身有问题应该从逻辑上去解决并改进代码

.检查异常,引起该异常的原因多种多样,比如说文件不存在、或者是连接错误等等。跟它的“兄弟”RuntimeException运行异常不同,该异常我们必须手动在代码里添加捕获语句来处理该异常,这也是我们学习java异常语句中主要处理的异常对象。

二、try-catch-finally语句
try块:负责捕获异常,一旦try中发现异常,程序的控制权将被移交给catch块中的异常处理程序。

注意!!---【try语句块不可以独立存在,必须与 catch 或者 finally 块同存】

catch块:如何处理?比如发出警告:提示、检查配置、网络连接,记录错误等。执行完catch块之后程序跳出catch块,继续执行后面的代码。

编写catch块的注意事项:多个catch块处理的异常类,要按照先catch子类后catch父类的处理方式,因为会由上自下处理异常,可以的到更加具体的报错】

finally:最终执行的代码,用于关闭和释放资源
 

 public class TryCatchTest {
 4     /**
 5      * divider:除数
 6      * result:结果
 7      * try-catch捕获while循环
 8      * 每次循环,divider减一,result=result+100/divider
 9      * 如果:捕获异常,打印输出“异常抛出了”,返回-1
10      * 否则:返回result
11      * @return
12      */
13     public int test1(){
14         int divider=10;
15         int result=100;
16         try{
17             while(divider>-1){
18                 divider--;
19                 result=result+100/divider;
20             }
21             return result;
22         }catch(Exception e){
23             e.printStackTrace();
24             System.out.println("异常抛出了!!");
25             return -1;
26         }
27     }
28     public static void main(String[] args) {
29         // TODO Auto-generated method stub
30         TryCatchTest t1=new TryCatchTest();
31         System.out.println("test1方法执行完毕!result的值为:"+t1.test1());
32     }
33     
34 }

 

public int test2(){
12         int divider=10;
13         int result=100;
14         try{
15             while(divider>-1){
16                 divider--;
17                 result=result+100/divider;
18             }
19             return result;
20         }catch(Exception e){
21             e.printStackTrace();
22             System.out.println("异常抛出了!!");
23             return result=999;
24         }finally{
25             System.out.println("这是finally,哈哈哈!!");
26             System.out.println("result的值为:"+result);
27         }
28         
29     }
30     
31     
32     
33     public static void main(String[] args) {
34         // TODO Auto-generated method stub
35         TryCatchTest t1=new TryCatchTest();
36         //System.out.println("test1方法执行完毕!result的值为:"+t1.test1());
37         t1.test2();
38         System.out.println("test2方法执行完毕!");
39     }

结果分析:我们可以从结果看出,finally语句块是在try块和catch块语句执行之后最后执行的。finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在finally执行前确定的;
这里有个有趣的问题,如果把上述中的test2方法中的finally语句块中加上return,编译器就会提示警告:finally block does not complete normally

public int test2(){
 2         int divider=10;
 3         int result=100;
 4         try{
 5             while(divider>-1){
 6                 divider--;
 7                 result=result+100/divider;
 8             }
 9             return result;
10         }catch(Exception e){
11             e.printStackTrace();
12             System.out.println("异常抛出了!!");
13             return result=999;
14         }finally{
15             System.out.println("这是finally,哈哈哈!!");
16             System.out.println("result的值为:"+result);
17             return result;//编译器警告
18         }
19         
20     }

 

分析问题: finally块中的return语句可能会覆盖try块、catch块中的return语句;如果finally块中包含了return语句,即使前面的catch块重新抛出了异常,则调用该方法的语句也不会获得catch块重新抛出的异常,而是会得到finally块的返回值,并且不会捕获异常。

解决问题:面对上述情况,其实更合理的做法是,既不在try block内部中使用return语句,也不在finally内部使用 return语句,而应该在 finally 语句之后使用return来表示函数的结束和返回。如:
 

 

 

 

1.不管有木有出现异常或者try和catch中有返回值return,finally块中代码都会执行;

  2、finally中最好不要包含return,否则程序会提前退出,返回会覆盖try或catch中保存的返回值。

  3.  e.printStackTrace()可以输出异常信息。

  4.  return值为-1为抛出异常的习惯写法。

  5.  如果方法中try,catch,finally中没有返回语句,则会调用这三个语句块之外的return结果。

 

 

  6.  finally 在try中的return之后 在返回主调函数之前执行.

 

三、throw和throws关键字
java中的异常抛出通常使用throw和throws关键字来实现。

throw ----将产生的异常抛出,是抛出异常的一个动作。

一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。如:
语法:throw (异常对象),如:
1 public static void main(String[] args) { 
2     String s = "abc"; 
3     if(s.equals("abc")) { 
4       throw new NumberFormatException(); 
5     } else { 
6       System.out.println(s); 
7     } 
8     //function(); 
9 } 

throws----声明将要抛出何种类型的异常(声明)。

当某个方法可能会抛出某种异常时用于throws 声明可能抛出的异常,然后交给上层调用它的方法程序处理。如:

1 public static void function() throws NumberFormatException{ 
 2     String s = "abc"; 
 3     System.out.println(Double.parseDouble(s)); 
 4   } 
 5     
 6   public static void main(String[] args) { 
 7     try { 
 8       function(); 
 9     } catch (NumberFormatException e) { 
10       System.err.println("非数据类型不能转换。"); 
11       //e.printStackTrace(); 
12     } 
13 } 

throw与throws的比较
1、throws出现在方法函数头;而throw出现在函数体。
2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

 

使用throw和throws关键字需要注意以下几点:
1.throws的异常列表可以是抛出一条异常,也可以是抛出多条异常,每个类型的异常中间用逗号隔开
2.方法体中调用会抛出异常的方法或者是先抛出一个异常:用throw new Exception() throw写在方法体里,表示“抛出异常”这个动作。
3.如果某个方法调用了抛出异常的方法,那么必须添加try catch语句去尝试捕获这种异常, 或者添加声明,将异常抛出给更上一层的调用者进行处理

 public static void main2(String[] args)  {
 
        int a = 0;
        try {
            System.out.println(10/a);
 
            int[] array = null;
            System.out.println(array.length);
            //程序既然已经发生异常了 说明这个业务是有问题的 所以下面的代码将不会被执行
            System.out.println("12334");
 
        }/*catch (ArithmeticException | NullPointerException e) {
            System.out.println("捕获到了异常!");
        }*/
       catch (ArithmeticException e) {
            e.printStackTrace();
            System.out.println("捕获到了算术异常!");
        }catch (NullPointerException e) {
            System.out.println("捕获空指针异常!");
        } catch (Exception e) {
            System.out.println("捕获到了异常!");
        }
        System.out.println("其他业务代码");
    }

 1 void doA(int a) throws (Exception1,Exception2,Exception3){
 2       try{
 3          ......
 4  
 5       }catch(Exception1 e){
 6        throw e;
          System.out.printfln("异常")
 7       }catch(Exception2 e){
 8        System.out.println("出错了!");
 9       }
10       if(a!=b)
11        throw new Exception3("自定义异常");
12 }

四,自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。

所有异常都必须是 Throwable 的子类。
如果希望写一个检查性异常类,则需要继承 Exception 类。
如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

public class MyException extends Exception {
 4      /**
 5      * 错误编码
 6      */
 7     private String errorCode;
 8 
 9    
10     public MyException(){}
11     
12     /**
13      * 构造一个基本异常.
14      *
15      * @param message
16      *        信息描述
17      */
18     public MyException(String message)
19     {
20         super(message);
21     }
22 
23    
24 
25     public String getErrorCode() {
26         return errorCode;
27     }
28 
29     public void setErrorCode(String errorCode) {
30         this.errorCode = errorCode;
31     }
32 
33 
34 }

public class Main {
 4 
 5     public static void main(String[] args) {
 6         // TODO Auto-generated method stub
 7         String[] sexs = {"男性","女性","中性"};
 8                   for(int i = 0; i < sexs.length; i++){
 9                       if("中性".equals(sexs[i])){
10                           try {
11                             throw new MyException("不存在中性的人!");
12                         } catch (MyException e) {
13                             // TODO Auto-generated catch block
14                             e.printStackTrace();
15                         }
16                      }else{
17                          System.out.println(sexs[i]);
18                      }
19                 } 
20     }
21 
22 }

 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐