【异常】

异常

1.1 异常概念

异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是:

  • 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

1.2 异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception,平常所说的异常指java.lang.Exception

在这里插入图片描述

Throwable体系:

  • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。
  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。

Throwable中的常用方法:

  • public void printStackTrace():打印异常的详细信息。

    包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

  • public String getMessage():获取发生异常的原因。

    提示给用户的时候,就提示错误原因。

  • public String toString():获取异常的类型和异常描述信息(不用)。

出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。

在这里插入图片描述

1.3 异常分类

/*
 *  异常分为编译异常和运行时期异常
 *    编译异常: 调用了抛出异常的方法,不处理编译失败  (try  throws)
 *    运行异常: 抛出的异常是RuntimeException类,或者是他的子类
 *  
 *  运行异常的特点:
 *     方法内部抛出的异常是运行异常, new XXXException
 *     方法的声明上,不需要throws语句,调用者,不需要处理
 *     设计原因:
 *        运行异常,不能发生,但是如果发生了,程序人员停止程序修改源代码
 *        
 *        运行异常: 一旦发生,不要处理,请你修改源代码, 运行异常一旦发生,后面的代码没有执行的意义
 */
public class RuntimeExceptionDemo {
	public static void main(String[] args) {
			double d = getArea(1);
			System.out.println(d);
	}
	
	/*
	 *  定义方法,计算圆形的面积
	 *  传递参数0,或者负数,计算的时候没有问题
	 *  但是,违反了真实情况
	 *  参数小于=0, 停止程序,不要在计算了
	 */
	public static double getArea(double r){
		if(r <= 0)
			throw new RuntimeException("圆形不存在");
		return r*r*Math.PI;
	}
	
	
	public static void function(){
		int[] arr = {1,2,3};
		//对数组的5索引进行判断,如果5索引大于100,请将5索引上的数据/2,否则除以3
		//索引根本就没有
		if(arr[5] > 100){
			arr[5] = arr[5]/2;
		}else{
			arr[5] = arr[5]/3;
		}
	}
}

1.4 异常的产生过程解析

在这里插入图片描述

第二章 异常的处理

Java异常处理的五个关键字:try、catch、finally、throw、throws

/*
 * 	异常的关键字 
 * 		throw 在方法的内部 抛出异常的对象
 * 			throw 后面 必须写new 对象  必须是异常的对象,必须是Exception或者子类
 * 
 * 
 * 	方法中声明异常关键字
 * 		throws  用于在方法的声明上,表明方法 可能出现异常
 * 		请调用者处理
 * 		throws 后面必须写异常类的类名
 * 
 * 
 * 	调用了一个抛出异常的方法,调用者就必须处理
 *  	不处理,编译失败 
 * 
 */
public class ExceptionDemo {
	public static void main(String[] args){
		int[] arr = {};
		try{
			int i = gerArray(arr);
			System.out.println(i);
		}catch (Exception e) {
			System.out.println(e);
		}
		System.out.println("Game Over");
		
		
	}
	//对数组的最后索引*2,返回
	private static int gerArray(int[] arr) throws Exception{
		//对方法参数进行合法性的判断,进行判断是不是null
		if(arr == null) {
			//抛出异常的形式,告诉调用者
			//关键字throw
			throw new Exception("传递数组不存在");
		}
		//对数组进行判断,判断数组中,是不是有元素
		if(arr.length == 0) {
			//抛出异常的形式,告诉调用者,数组没有元素
			throw new Exception("数组中没有任何元素");
		}
		int i = arr[arr.length-1];
		return i*2;
	}
}

异常的处理方式:
	try...catch...finally
	try{
 		被检测的代码
 		可能出现异常的代码
	}catch(异常类名 变量){
		异常的处理方式
		循环,判断,调用方法,变量
 	}finally{
		必须执行的代码
 	}

try该代码块中编写可能产生异常的代码。

catch用来进行某种异常的捕获,实现对捕获到的异常进行处理。

在这里插入图片描述
演示如下:

/*
 *  	异常的处理方式:
 *  	try...catch...finally
 *  	try{
 *  		被检测的代码
 *  		可能出现异常的代码
 *  	}catch(异常类名 变量){
 *  		异常的处理方式
 *  		循环,判断,调用方法,变量
 *  	}finally{
 *  		必须执行的代码
 *  	}
 */
 public class ExceptionDemo3 {
	public static void main(String[] args) {
		try{
			function(0);
		}catch(Exception ex){
			System.out.println(ex);
		
		}finally{
			System.out.println("代码必须执行");
		}
	}
	
	public static void function(int a)throws Exception{
		if( a == 0)
			throw new Exception();
		System.out.println(a);
	}
	
}
/*
 *  多catch写在一起
 *  细节:
 *    catch小括号中,写的是异常类的类名
 *    有没有顺序的概念,有
 *    
 *    平级异常: 抛出的异常类之间,没有继承关系,没有顺序
 *      NullPointerException extends RuntimeException
 *      NoSuchElementException extends RuntimeException
 *      ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException extends RuntimeException
 *      
 *    上下级关系的异常
 *      NullPointerException extends RuntimeException extends Exception
 *      越高级的父类,写在下面
 */
public class ExceptionDemo1 {
	public static void main(String[] args){
		int[] arr = {};
		try{
			int i = gerArray(arr);
			System.out.println(i);
		}catch (NullPointerException ex) {
			System.out.println("###"+ex);
		}catch(ArrayIndexOutOfBoundsException ex) {
			System.out.println("!!!"+ex);
		}
		System.out.println("Game Over");
		
		
	}
	/*
	 * 定义方法,抛出异常
	 * 	调用者使用try catch
	 */

	private static int gerArray(int[] arr) throws NullPointerException,ArrayIndexOutOfBoundsException{
		//对数组判空
		if(arr == null) {
			//手动抛出异常,抛出空指针异常
			throw new NullPointerException("数组不存在");
		}
		//对数组索引进行判断
		if(arr.length < 3) {
			//手动抛出异常,抛出数组越界异常
			throw new ArrayIndexOutOfBoundsException("数组没有3索引");
		}
		return arr[3]+1;
	}
}
/*
 * 	 继承后,在子类重写方法的时候,异常处理
 * 	结论:
 * 		父类的方法,如果抛出异常,子类重写后
 * 		可以不抛出异常
 * 		也可以抛出异常,但是如果子类要抛,抛出的异常不能大于父类的异常
 * 		大于,都是指的时继承关系
 *	
 */
 public class ExceptionDemo {
	public static void main(String[] args) {
		Fu f = new Zi();
		f.function();
	}
}

class Fu{
	public void function(){
		
	}
}
class Zi extends Fu{
	public void function(){
		
			
				try {
					method();
				} catch (Exception e) {
					
					e.printStackTrace();
				}
			
				
			
	
	}
	public void method()throws Exception{
		
	}
}



在这里插入图片描述
如何获取异常信息:

Throwable类中定义了一些查看方法:

 /*
 *  Throwable类中的方法
 *  	三个方法,都和异常的信息有关系
 *    		String getMessage() 对异常信息的详细描述       异常了!
 *   	 	String toString()   对异常信息的简短描述       java.lang.Exception: 异常了!
 *    		void printStackTrace() 将异常信息追踪到标准的错误流  异常信息最全,JVM默认调用方法也是这个方法
 */
public class ExceptionDemo1 {
	public static void main(String[] args) {
	  try{	 
		function();
	  }catch(Exception ex){
		  //System.out.println(ex.toString());
		  ex.printStackTrace();
	  }
	}
	
	public static void function() throws Exception{
		throw new Exception("异常了!");
	}
}

finally 代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

什么时候的代码必须最终执行?

当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。

finally的语法:

try…catch…finally:自身需要处理异常,最终还得关闭资源。

注意:finally不能单独使用。

比如在我们之后学习的IO流中,当打开了一个关联文件的资源,最后程序不管结果如何,都需要把这个资源关闭掉。

finally代码参考如下:

public class TryCatchDemo4 {
    public static void main(String[] args) {
        try {
            read("a.txt");
        } catch (FileNotFoundException e) {
            //抓取到的是编译期异常  抛出去的是运行期 
            throw new RuntimeException(e);
        } finally {
            System.out.println("不管程序怎样,这里都将会被执行。");
        }
        System.out.println("over");
    }
    /*
     *
     * 我们 当前的这个方法中 有异常  有编译期异常
     */
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }
}

当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

自定义异常

概述

为什么需要自定义异常类:

我们说了Java中不同的异常类,分别表示着某一种具体的异常情况,那么在开发中总是有些异常情况是SUN没有定义好的,此时我们根据自己业务的异常情况来定义异常类。例如年龄负数问题,考试成绩负数问题等等。

在上述代码中,发现这些异常都是JDK内部定义好的,但是实际开发中也会出现很多异常,这些异常很可能在JDK中没有定义过,例如年龄负数问题,考试成绩负数问题.那么能不能自己定义异常呢?

什么是自定义异常类:

在开发中根据自己业务的异常情况来定义异常类.

自定义一个业务逻辑异常: RegisterException。一个注册异常类。

异常类如何定义:

  1. 自定义一个编译期异常: 自定义类 并继承于java.lang.Exception
  2. 自定义一个运行时期的异常类:自定义类 并继承于java.lang.RuntimeException

自定义异常的练习

/*
 * A: 自定义异常的定义
 * a:通过阅读源码,发现规律:
 *		每个异常中都调用了父类的构造方法,把异常描述信息传递给了父类,让父类帮我们进行异常信息的   封装。
 *		 b:格式:
 *			Class 异常名 extends Exception{ //或继承RuntimeException
 *				public 异常名(){
 *				}
 *				public 异常名(String s){ 
 *					super(s); 
 *				}
 *			}	
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		
		int avg = getAvg(50,60,-70,80);
		System.out.println(avg);
		
	}
	/*
	 * 传递成绩,计算成绩的平均数
	 * 成绩没有负数,需要抛出异常,停止运算
	 */
	public static int getAvg(int...source){
		int sum = 0 ;
		for(int s : source){
			if( s < 0){
				throw new FuShuException("成绩错误 "+s);
			}
			sum = sum + s;
		}
		return sum/source.length;
	}
}

/*
 *  自定义异常
 *    继承Exception,或者继承RuntimeException
 *    构造方法中,super将异常信息,传递给父类
 */
public class FuShuException extends RuntimeException{
	public FuShuException(String s){
		super(s);
	}
	
	public FuShuException(){}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值