zoukankan      html  css  js  c++  java
  • Java中的异常

    一、什么是异常

    异常(Exception)定义了程序中遇到的非致命的错误, 而不是编译时的语法错误。如果程序中有异常而没有处理,一般可以通过编译,但运行时会发生错误。

    先看下面这个例子:

    class A
    {
    	public int divide(int a, int b)
    	{
    		int m = 0;
    		m = a/b;
    		return m;
    	}
    }
    
    public class TestExcept
    {
    	public static void main(String[] args)
    	{
    		new A().divide(6, 0);                //除数为0,可以通过编译运行会报错
    		System.out.printf("测试异常
    ");    //15行抛出异常,该语句不会运行
    	}
    }
    
    运行的结果为:

    -------------------------------------------------------------------------------------------------

    Exception in thread "main" java.lang.ArithmeticException: / by zero
            at A.divide(TestExcept.java:6)
            at TestExcept.main(TestExcept.java:15)

    -------------------------------------------------------------------------------------------------

    上面的程序运行的结果报告发生了算术异常(ArithMethicException),系统不再执行下去,提前结束,这种情况就是我们所说的异常。


    二、异常的分类


    1、Error是系统错误,编译时就会报错,程序员无法处理

    2、Exception是程序员可以捕获并处理的异常

    3、RuntimeException的子类异常时可以处理也可以不处理的异常

    4、凡是继承自Exception但又不是RuntimeException子类的异常,必须进行捕获和处理


    三、异常处理机制

    当Java程序运行发生异常时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象。然后把该异常对象提交给Java虚拟机,Java虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则程序终止。程序员可以自己编写代码来捕获可能出现的异常,并编写代码来处理相应的异常,其中可以用来处理异常的一种方式便是try..catch语句。

    try..catch语句的用法:

    try 
    {  
        // 可能会发生异常的程序代码  
    } 
    catch(ExceptionName1 id1){  
        // 当产生ExceptionName1异常时的处理措施 
    }  
    catch(ExceptionName2 id2){  
         //当产生ExceptionName2异常时的处理措施  
    } 
    ....
    finally
    {
    	//无论是否捕获到异常都必须处理的代码
    }
    
    注意:

    1、所有的catch只能有一个被执行

    2、有可能所有的catch都没有执行,但finally一定会执行

    3、要先catch子类异常在catch父类异常,否则会报错

    4、当try 代码块中的语句发生了异常,程序就会跳转到catch 代码块中执行,执行完catch 代码块中的程序代码后,系统会继续执行catch 代码块后的其他代码,但不会执行try 代码块中发生异常语句后的代码

    例子:

    class A
    {
    	public int divide(int a, int b)
    	{
    		int m = 0;
    		m = a/b;
    	
    		return m;
    	}
    }
    
    public class TestExcept_1
    {
    	public static void main(String[] args)
    	{
    		A aa = new A();
    		
    		try
    		{
    			aa.divide(6,0);
    			System.out.printf("测试异常1
    ");     //该语句不会运行
    		}
    		catch(ArithmeticException e)
    		{
    			System.out.printf("测试异常2
    ");
    		}
    		catch(NullPointerException e)
    		{
    			System.out.printf("测试异常3
    ");		
    		}
    		catch (Exception e)  		//不能写在前面,否则会报错,因为Exception是ArithmeticException和NullPointerException的父类
    		{
    			System.out.printf("测试异常4
    ");
    		}
    		finally
    		{
    			System.out.printf("测试异常5
    ");
    		}
    	}
    }
    
    
    运行结果为:

    ---------------------------------------------------------------------------------------------------------

    测试异常2
    测试异常5

    ----------------------------------------------------------------------------------------------------------
    分析:

    当try 代码块中的程序发生了异常,系统将这个异常发生的代码行号,类别等信息封装到一个对象中,并将这个对象传递给catch 代码块。catch 关键字后跟有一个用括号括起来的Exception 类型的参数e,这跟我们经常用到的如何定义一个函数接收的参数格式是一样的。括号中的Exception 就是try 代码块传递给catch 代码块的变量类型,e 就是变量名,所以我们也可以将e 改用成别的名称(如ex 等)


    四、throws关键字

    针对上面的例子,我们假设TestExcept_1类与A类不是同一个人写的,写TestExcept_1类的人,在main 方法中调用A类的devide 方法时,怎么能知道devide 方法有可能出现异常情况呢?他又怎么能够想到要用try catch 语句去处理可能发生的异常呢?

    问题可以这样解决,只要写A类的人,在定义devide 方法时,在devide 方法参数列表后用throws 关键字声明一下,该函数有可能发生异常及异常的类别。这样,调用者在调用该方法时,就必须用try…catch 语句进行处理,否则,编译将无法通过。

    如下面的程序代码:

    class A
    {
    	public int divide(int a, int b) throws ArithmeticException
    	{
    		int m = 0;
    		m = a/b;
    		return m;
    	}
    }
    
    public class TestExcept_2
    {
    	public static void main(String[] args)
    	{
    		new A().divide(6, 0);                //调用了divide方法但没有进行处理,程序运行会报错
    		System.out.printf("测试异常
    ");   
    	}
    }
    
    运行结果为:

    ------------------------------------------------------------------------------------------------------------------------------------------------

    Exception in thread "main" java.lang.ArithmeticException: / by zero
            at A.divide(TestExcept.java:6)
            at TestExcept.main(TestExcept.java:15)

    ------------------------------------------------------------------------------------------------------------------------------------------------

    注意:

    void f() throws A
    {
    	....
    }

    1、throws A表示调用f方法时可能会抛出A类异常,建议调用f方法时做好对f方法可能抛出的A类异常进行捕获

    2、throws A并代表f方法一定会抛出A类异常

    3、throws A 不代表调用f方法是,必须对A异常进行捕获。假如A是RuntimeException子类异常,则编译器允许可以不进行处理

    建议:

    1、对throws出的所有异常进行处理

    2、如果一个方法内部已经对A异常进行了处理。则就不要再throws A


    五、自定义异常

    除了系统提供的异常,我们也可以定义自己的异常类,自定义的异常类必须继承Exception 类。

    throw关键字:

    throw用来抛出异常,其格式为:

    throw new 异常名(参数);

    具体怎么自定义异常看下面这个例子:

    class XxxException extends Exception     //自定义异常XxxException
    {
    	public XxxException(String name)
    	{
    		super(name);                    //继承父类的构造方法
    	}
    }
    class YyyException extends Exception    //自定义异常XxxException
    {
    	public YyyException(String name)
    	{
    		super(name);
    	}
    }
    class A 
    {
    	public int x;
    	public A(int x)
    	{
    		this.x = x;
    	}
    	public void fun() throws XxxException, YyyException
    	{
    		if(x==0)
    			throw new YyyException("Yyy");  //抛出异常
    		if(x==1)
    			throw new XxxException("Xxx");   //抛出异常
    	}
    }
    
    public class TestExcep_2
    {
    	public static void main(String[] args)
    	{
    		A aa = new A(0);
    		
    		try
    		{
    			aa.fun();
    		}
    		catch(YyyException e)
    		{
    			System.out.printf("测试异常1
    ");
    			e.printStackTrace();            //打印出异常的具体信息
    		}
    		catch(XxxException e)
    		{
    			System.out.printf("测试异常2
    ");		
    			e.printStackTrace();
    		}
    		catch (Exception e)
    		{
    			System.out.printf("测试异常3
    ");
    			e.printStackTrace();
    		}
    		finally
    		{
    			System.out.printf("测试异常4
    ");
    		}
    	}
    }
    
    
    输出结果:

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------

    测试异常1
    YyyException: Yyy
            at A.fun(TestExcep_2.java:25)
            at TestExcep_2.main(TestExcep_2.java:39)
    测试异常4

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------


  • 相关阅读:
    JS计算每个字符出现的次数
    FCL研究-目录
    FCL研究-LINQ-System.Linq Enumerable
    FCL研究-集合- System.Collections 接口和对象集合
    Vimperator常用快捷键
    【转】WCF光芒下的Web Service
    【转】GridView 加载空行并点击编辑每一个单元格
    [转]在C#程序设计中使用Win32类库
    OpenOffice实现Office转Pdf(支持自定义添加水印、页眉、页脚)
    VUE 动态路由
  • 原文地址:https://www.cnblogs.com/yzy-blogs/p/6597338.html
Copyright © 2011-2022 走看看