Java——异常

异常:Java运行时期发生的问题就是异常。

Java中运行时发生的除了异常Exception还要Error。

【Exception与Error】

异常:通常可以有针对性的处理方式。

错误:通常是系统级别的问题,都是Java所在系统发生的并反馈给Java的。无法针对处理,只能修正代码。

1. throw用在函数内,抛出异常对象,并可以结束函数。

public class ArrayException {
	int getElement(int[] a,int index)
	{
		if(a==null)
		{
			throw new NullPointerException("该数组不存在");
		}
		if(index<0||index>=a.length)
		{
			throw new ArrayIndexOutOfBoundsException("错误的角标"+index+"越界!");
		}
		return a[index];
	}
}


public class Demo {
	public static void main(String[] args) {
		ArrayException ex=new ArrayException();
		int[] b= {23,12,54,232};
		int num=ex.getElement(null, 4);
		System.out.println(num);
	}
}

(小练习:https://blog.csdn.net/weixin_43677405/article/details/104108362


【自定义异常】

 前面出现的几个异常都是Java定义好的异常,Java通过类进行的描述,并将问题封装成对象,这是符合面向对象的思想的。所以可以有自定义异常。

自定义异常被抛出,必须是继承Throwable,或者继承Throwable的子类。该对象才可以被throw抛出。

public class IllegalAgeException extends RuntimeException{
   public IllegalAgeException() 
   {
	   super();
   }
   IllegalAgeException(String s)
   {
	   super(s);//如果自定义异常需要异常信息,可以通过调用父类的带有字符串参数的构造函数即可。
   }
}


public class Person {
	private String name;
	private int age;
	Person(String name,int age) {
		if(age<0||age>200)
		{
			throw new IllegalAgeException("输入的年龄非法!");
		}
		this.name=name;
		this.age=age;
	}
	
	public String toString()
	{
		return "Person[name"+name+",age="+age+"]";		
	}
}


public class PersonDemo {
	public static void main(String[] args) {
	Person p=new Person("Tom", -13);
	System.out.println(p);
	}
}

上面这个例子,IllegalAgeException自定义异常到底继承Exception还是RuntimeException呢?

继承Exception,必须要throws声明,一声明就告知调用者进行捕获,一旦问题处理了调用者的程序会继续执行

如果继承RuntimeException,不需要throws声明,因为调用者根本不知道问题所在,所以也不可能编写捕获代码。一旦发生了IllegalAgeException,调用者程序会停止,并Jvm将信息显示到屏幕,让调用者看到问题,修正代码。


【问题】

1. 继承Exception和继承RuntimeException有什么区别?

Exception会导致编译失败,因为编译器在检查语法时会发生错误。

RuntimeException不是功能本身的发生的异常,比如调用者传递参数错误而导致运行失败。这个异常不要声明出来。(声明的目的是为了让调用者进行处理。不声明的目的是不让调用者进行处理,就是为了让程序停止,让调用者看到现象,并进行代码的修正。)


2. 什么是捕获,什么是声明?(即要么把问题处理,要么把问题说出来让调用者知道。)

声明:将问题标识出来,报告给调用者。

如果函数内通过throw抛出编译异常,而捕获,那么必须通过throws进行声明,让调用者去处理。

捕获:Java对异常有针对性的语句进行捕获。

public class exception {
void show(int a) throws Exception
{
	if(a>0)
		throw new Exception();
	else
		System.out.println("show run");
}
}


public class ExceptionDemo {
	public static void main(String[] args) {
		exception d=new exception();
		try 
		{
			d.show(2);		
		}
		catch(Exception ex)
		{
			System.out.println("发生异常!");
		}
        System.out.println("hello world!");
	}
}

3. 异常分类

答:1.编译时异常,编译器会检测的异常。

       2. 运行异常,编译器不会检测的异常,可声明亦可不声明。如果声明了,无外乎就是让调用者给出处理方式。


(运行时异常的小练习:https://blog.csdn.net/weixin_43677405/article/details/104114523

(编译时的异常的小练习:https://blog.csdn.net/weixin_43677405/article/details/104115220


【类型转换】
当我们抛出的异常对象处理不了的话,我们就需要将这个异常传换为接收异常可以处理的异常,这时就需要异常的转换了。

比如上面这个例子,

public void Educate()throws MaoYanException

对Teacher抛出电脑冒烟的问题,老师群体是处理不了的,所以我们就需要将MaoYanException转换成老师可以处理的异常,如NoPlanException。

public void Educate()throws NoPlanException
public class LanPingException extends Exception{
	public LanPingException() {
		super();
	}
    public LanPingException(String message)
    {
    	super(message);
    }
}


public class MaoYanException extends Exception {
   public MaoYanException() {
	super();
}
   public MaoYanException(String message)
   {
	   super(message);
   }
}


public class NoPlanException extends Exception {
   public NoPlanException() {
	super();
   }
   public NoPlanException(String message)
   {
	   super(message);
   }
}


public class NoteBook {
   private int state=2;
   public void run()throws LanPingException,MaoYanException
   {
	   if(state==1)
		  throw new LanPingException("电脑蓝屏了!");
	  if(state==2)
		  throw new MaoYanException("电脑冒烟了!");
	  System.out.println("电脑运行!");
   }

   public void reset()
   {
	   state=0;
    }
}


public class Teacher {
	private String name;
	private NoteBook notebook;
	public Teacher(String name) 
	{
		this.name=name;
		notebook=new NoteBook();
	}
	
	public void Educate()throws NoPlanException
	{
		try
		{
			notebook.run();
		}
		catch(LanPingException ex)
		{
			System.out.println(ex.toString());
			notebook.reset();
		}
		catch (MaoYanException e) {
			System.out.println(e.toString());
			throw new NoPlanException();//将MaoYanException转为为老师可以处理的NoPlanException
		}
		System.out.println("讲课!");
	}
}


public class TeacherDemo {
	public static void main(String[] args) {
		Teacher t=new Teacher("Tom");
		try 
		{
			t.Educate();	
		}
		catch(NoPlanException e)
		{
			System.out.println("放假!");
		}
	}
}

【throw和throws的区别】
1. throw用在函数内,throws用在函数上。

2. throw抛出的是异常对象,throws用于进行异常的声明,后面异常可以有多个,用逗号隔开。

public void run()throws LanPingException,MaoYanException
{
	if(state==1)
		throw new LanPingException("电脑蓝屏了!");
	if(state==2)
		throw new MaoYanException("电脑冒烟了!");
	System.out.println("电脑运行!");
}

【finally的使用】
  有一些特定的代码无论异常是否发生,都需要执行。但是,异常会引发程序的跳转,导致有些语句执行不到,无法满足这个需求。异常捕获处理时,Java提供解决方案:try catch finally,finally解决这个问题,这个代码块中存放的代码都是一定会被执行的。(但是,也有不执行的,System.exit(0)

public class FinException extends Exception{
  public FinException() {
	super();
}
  public FinException(String message) {
		super(message);
	}
}


public class Fin {
	void show (int a)throws FinException
	{
		if(a<0)
			throw new FinException("数值非法");
		System.out.println("number="+a);
	}
}


public class FinDemo {
	public static void main(String[] args) {
		Fin f=new Fin();
		try
		{
			f.show(-7);
			System.out.println("***");//如果上一句有异常,那么这句话不执行,直接跳转到catch里
	    }
        catch(FinException ex)
        {
        	System.out.println(ex.getMessage());
        	//return;//这里使用return,在执行return之前会执行finally,最后的输出“over”不会执行
        	//System.exit(0);//如果这里使用System.exit(0)连finally都不会执行
        }
		finally
		{
			System.out.println("hello");
		}
		System.out.println("over");
	}
}

如果finally里有结束语句的语句,那么catch如果有return,就不会执行catch的return语句了。

int show(int num)
	{
		try 
		{
              if(num<0)
            	 throw new Exception();
              return 4;
		}
		catch(Exception ex)
		{
			 System.out.println(ex.toString());
			 return 100;
		}
		finally
		{
			 return 200;
		}
	}

如果我传的num=-1, int a=show(-1),a得到的值为200,因为在catch的return之前会执行return 200,而catch的return不会执行。

问题:finally什么时候用呢?

答:只要程序中使用到了具体的资源(数据库连接,IO资源,网络连接socker等)。需要释放,都必须定义在finally中。只要问题发生与否,指定程序都需要执行时,就定义在finally中。

【try catch finally的组合方式】
1. try catch: 可以对代码进行代码异常检测。并对检测的异常传递给catch处理。                                                                                                 异常捕获处理。

//这时不需要写throws,因为在catch里将已捕获了Exception
void show()
	{
		try
		{
			throw new Exception();
		}
		catch(Exception ex)
		{
			//...
		}
	}


//这时需要写throws
void show()throws Exception
	{
		try
		{
			throw new Exception();
		}
		catch(Exception ex)
		{
			try
			{
				throw ex;
			}
			catch(Exception e)
			{
				throw e;//最后在这里还是将异常往外抛,所以要在方法头写throws
			}
		}
	}

2. try finally: 对代码进行异常检测,检测到异常后,因为没有catch,本方法无法处理该异常,所以一样会被默认jvm抛出。
                    异常时没有捕获处理,finally里可以完成一些关闭资源的操作。

//要写throws
	void show()throws Exception
	{
		try
		{
			throw new Exception();
		}
		finally
		{
			//可以做一些关闭资源等操作
		}
	}

3. try catch finally: 检测异常,并传递给catch,并定义资源释放。

4. try catch(1)   catch (2)  ...


【异常在覆盖中的细节】
 1. 子类覆盖父类方法时,如果父类的方法声明异常,子类只能证明父类异常或者异常的子类,或者不声明

 2. 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集

3. 当被覆盖的方法没有异常声明时,子类声明时也无法声明异常。(但是,可以声明RuntimeException)这种情况存在于继承和接口中。

     问题:如果接口中没有声明异常,而实现的子类覆盖方法时发生了异常该怎么办?

     答:无法进行throws声明,只能catch的捕获。如果问题处理不了,catch中继续throw抛出,但是只能将异常转换成RuntimeException子类抛出。

public interface Inter {
  public void show();
}


public class InterDemo implements Inter{
   public void show()throws RuntimeException
   {
	   try 
	   {
		   throw new Exception();//这个是无法声明的,只能通过catch捕获,将其转换为RuntimeException才可声明
	   }
	   catch(Exception e)
	   {
		   throw new RuntimeException();
	   }
   }
}

           

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值