编译时异常和运行时异常的小细节

      学到异常处理了,于是想记录下Java异常处理的细节,以增加对异常处理的印象。

    Java常见的异常类之间的继承关系:

    

      (仿李刚老师的《疯狂Java讲义》异常章节的图)

      Java的异常被分为两大类:Checked异常(编译时出现异常)和Runtime(运行时异常)。

           1、编译时被检测的异常,除了特殊子类RuntimeException体系的,只要是Exception和其子类都是。
         这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
           2、编译时不检测异常(运行时异常),就是Exception中的RuntimeException和其子类,这种问题的发生,让                   功能无法继续,运算也无法进行,更多是因为调用的原因导致的。或者引发程序内部状态改变,导致异                       常。这种问题一般不处理,直接编译通过,在运行时,调用者调用时引发异常从而程序强制停止,此时调用者即可对异常进行修正。

            异常Demo演示:

public class First
{
	private int num;
	
	public void change(String str)
	{
		int a = Integer.parseInt(str);
		this.num = a;
	}
	
	public static void main(String[] args)
	{
		First f = new First();
		f.change("one");
	}
}
/*
编译这段代码后,运行出现NumberFormatException异常,这是一个运行时异常
*/
增加一个自定义的异常处理类:

class MyException extends Exception    //自定义一个异常类,
{
	/*如果将MyException继承自RuntimeException,就没有后面的故事了,呵呵!
	 *这样后,MyException就是一个运行时异常,从下面的叙述中,
	 *你应该能看出运行时异常和编译时异常的区别吧
	*/
		public MyException(){}
		public MyException(String msg)
		{
			super(msg);
		}
}
public class First
{
	private int num;
	
	public void change(String str)
	{
		try 
		{
			int a = Integer.parseInt(str);
			this.num = a;
		}
		catch(Exception e)
		{
			throw new MyException("You should pass a integer string.");  //抛出自定义异常
		}

	}
	
	public static void main(String[] args)
	{
		First f = new First();
		f.change("one");
	}
}
/*
编译这段代码后,出现错误:
First.java:22: error: unreported exception MyException; must be caught or declared to be thrown
                        throw new MyException("You should pass a integer string.");  //??????????
??
                        ^
1 error
*/

    "未报告的异常,必须被捕获或者声明",此处编译不能通过,对于自定义的异常类属于编译时异常,需要在函数在函数出进行声明,代码改成如下:

class MyException extends Exception    //自定义一个异常类
{
	public MyException(){}
	public MyException(String msg)
	{
	    super(msg);
	}
}
public class First
{
	private int num;
	
	public void change(String str) throws MyException     //在方法声明上抛出,是为了告诉调用者,你注意了,我有问题
	{
		try 
		{
			int a = Integer.parseInt(str);
			this.num = a;
		}
		catch(Exception e)   
		{
			throw new MyException("You should pass a integer string.");  //抛出自定义异常
		}

	}
	
	public static void main(String[] args)
	{
		First f = new First();
		f.change("one");
	}
}
/*
编译这段代码后,出现错误:
First.java:30: error: unreported exception MyException; must be caught or declared to be thrown
                f.change("one");
                        ^
1 error

*/
    为什么还是不能编译通过呢?一开始在change()方法体内遇到throw new MyException("You should pass a integer string.");  准备抛出异常,可是change()方法没有显示声明这个异常,对于编译性的异常,需要显示进行声明,让JVM知道后续程序运行时该怎么处理。后来在change()方法声明了我的自定义异常:public void change(String str) throws MyException,所以change()方法中的MyException异常被抛到调用change()方法的main主函数中,所以出现了上面的错误,因而也需要在main主函数声明MyException。下面是正确代码:

class MyException extends Exception    //自定义一个异常类
{
		public MyException(){}
		public MyException(String msg)
		{
			super(msg);
		}
}
public class First
{
	private int num;
	
	public void change(String str) throws MyException
	{
		try 
		{
			int a = Integer.parseInt(str);
			this.num = a;
		}
		catch(Exception e)
		{
			throw new MyException("You should pass a integer string.");  //抛出自定义异常
		}

	}
	
	public static void main(String[] args) throws MyException  //这里抛出自定义异常,但我们在程序开发时,通常不这么做
	{
		First f = new First();
		f.change("one");
	}
}
/**
Exception in thread "main" MyException: You should pass a integer string.
        at First.change(First.java:22)
        at First.main(First.java:30)
*/
     编译、运行上面的代码后,最终的MyException异常被抛给JVM,JVM打印出异常跟踪栈。对于这样的异常,可以进行必要的try catch操作。如:

class MyException extends Exception    //自定义一个异常类
{
		public MyException(){}
		public MyException(String msg)
		{
			super(msg);
		}
}
public class First
{
	private int num;
	
	public void change(String str) throws MyException // 注:如果MyException是一个RuntimeException, 这里就不用声明抛出了
	{
		try 
		{
			int a = Integer.parseInt(str);
			this.num = a;
		}
		catch(Exception e)
		{
			throw new MyException("You should pass a integer string.");  //抛出自定义异常
		}

	}
	
	public static void main(String[] args)
	{
		First f = new First();
		try
		{
	             f.change("one");
		}
		catch(MyException e)   //直接捕获并处理了
		{
		    System.out.println("error: " + e.getMessage());
		}
	}
}
    再对比一个编译时异常的例子:

import java.io.IOException;
import java.io.FileInputStream;
public class Second
{
	public void fileTest()
	{
		FileInputStream fis = null;
		try 
		{
			fis = new FileInputStream("no-such-a-file.txt");
		}
		catch(Exception e)
		{
			throw new IOException();
		}

	}
	
	public static void main(String[] args)
	{
		Second f = new Second();
		f.fileTest();
	}
}
也会出现:

Second.java:14: error: unreported exception IOException; must be caught or declared to be thrown
                        throw new IOException();
                        ^
1 error

    IOException是编译时异常,这样的错误, 所以你还是得在方法体上声明IOException,对于RuntimeException是不需要声明的。See next:

import java.io.IOException;
import java.io.FileInputStream;
public class Second 
{
	public void fileTest() throws IOException
	{
		FileInputStream fis = null;
		try 
		{
			fis = new FileInputStream("no-such-a-file.txt");
		}
		catch(Exception e)
		{
			throw new IOException();
		}

	}
	
	public static void main(String[] args)  throws IOException
	{
		Second f = new Second();
		f.fileTest();
	}
}

    这样就不会在编译时出现情况了,这算是应该注意的一个小细节吧。

   下面再来看一个RuntimeException不需要声明的例子:

class MyException3 extends RuntimeException {
    private String message;

    public MyException3() {
    }

    public MyException3(String mess) {
        message = mess;
    }

    public String getMessage() {
        return message;
    }
}

public class NotDeclareRuntimeExceptionTest {
    
    public static void runtimeExceptionTest1(int n) {   //这里不用声名抛出的异常 MyException3
        if (n == 1) {
            throw new MyException3();
        } else {
            System.out.println("dd");
        }
    }

    public static void main(String[] args) {
        System.out.println("ok");
    }


}

参考博客:

http://www.blogjava.net/fancydeepin/archive/2015/10/15/382508.html 

http://blog.csdn.net/hguisu/article/details/6155636








  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值