Java中异常机制

一、概述

  1. 异常是一套用于反馈和处理问题的机制
  2. Throwable 是所有异常和错误的顶级父类
  3. Throwable派生出两个类Error和Exeption

二、Error

  1. 出现在代码逻辑没有错误,因外界因素或环境因素导致的严重错误的情况。
  2. 一旦出现,无法修改

三、Exception

  1. -异常,代表了程序在编译和运行时发生的各种不期望发生的事件。是java异常处理的核心。
  2. 非检查是异常(运行时异常):
    1. -编译时不会报错,运行时报错,往往是语法正确,但是逻辑错误。 
    2. 编译前可以处理,也可以不处理。
    3. 一个小的父类 --- RuntimeException
  3. 检查异常(编译时异常):
    1. 编译时已经出现,一旦出现,则必须处理
    2. 要么抛出,要么捕获

    四、异常的捕获

    	public static void main(String[] args) {
    
    		// System.out.println(1 / 0);
    
    		try {
    			int[] arr = new int[3];
    			System.out.println(arr[5]);
    		} catch (ArrayIndexOutOfBoundsException e) {
    			System.out.println();
    		}
    
    	}

    1. 多个异常可以同时处理,用多个catch捕获
    2. 如果所有异常的处理方式都一样,可以用统一的Exception一次捕获
    3. 多个异常分组处理,在同一组异常之间可以用"|"隔开。(从JDK1.7开始)
      try {
      			String msg = readFile(null);
      			System.out.println(msg);
      		} catch (PathNotExistException | FileCannotReadException e) {
      			// 打印栈轨迹
      			e.printStackTrace();
      			// System.out.println(e.getMessage());
      		} catch (Exception e) {
      		} finally {
      			System.out.println("文件释放");
      		}

    4. 如果方法抛出的是父类异常,则必须要一以父类异常捕获
    5. 在捕获异常 时,要求先捕获子类异常,在捕获父类异常。否则子类异常将永远无法捕获到。

    五、排查异常

    1. 查看异常的名字
    2. 查看异常信息
    3. 从栈轨迹尾端开始看起(控制台从上至下)。
    注意:如果异常最终抛给了JVM,那么JVM默认打印 这个异常的栈轨迹。

    六、异常的自定义

    1. 当一个类继承Exception,则默认是编译时异常
    2. 当一个类继承RuntimeException时,才是运行是异常。
    3. 一个类继承运行时异常类,那么这个类就是运行时异常;反之,则为编译时异常。
    public class Demo_01 {
    	public static void main(String[] args) {
    		try {
    			String str = readFile("C:\\ a.txt");
    		} catch (FileCannotReadException e) {
    			//打印异常信息
    			System.out.println(e.getMessage());
    			//打印栈轨迹
    			e.printStackTrace();
    			//查看异常: 1. 查看异常名字 2. 查看异常信息 3. 从栈轨迹尾端开始排查(控制台中从上致下)
    			//如果异常最终抛给了JVM,JVM默认打印这个异常的栈轨迹
    		}
    	}
    	
    	private static String readFile(String string) throws FileCannotReadException {
    		//如果是是以C开头,则认为这个文件不可被读取
    		if(string  == null){
    			//运行时异常,可以处理,也可以不处理
    			throw new NullPointerException("路径不能为空");
    		}else
    		if(string.startsWith("C")){
    			//编译时异常一定要处理
    			throw new FileCannotReadException("文件不能被读取");
    		}
    		return null;
    	}
    }
    //当一个类继承Exception时,默认是编译时异常
    	//如果一个类继承的时RuntimeException,才会称为一个运行时异常
    	//一个类继承编译时异常,则这个类时编译时异常。反之为运行时异常。
    class FileCannotReadException extends Exception{
    	public FileCannotReadException() {}
    	public FileCannotReadException(String msg){
    		super(msg);
    	}
    }

    七、异常方法的重写和重载

    1. 异常不会影响方法的重载。当一个类中方法名一致,但参数列表不一致时发生方法的重载,方法的重载和修饰符、返回值类型、异常都没有关系。
    2. 在重写父类的异常方法时,子类重写的方法抛出的异常不能超出 父类异常方法抛出异常的范围(编译时异常的要求)。方法重写时必须遵循两小两大一小原则。(参考:http://blog.csdn.net/chou_out_man/article/details/77976679)
    3. 子类不能抛出范围比父类 更大的异常 --- 针对的是编译时异常 , 但对运行时异常 。 
      class A {
      
      	public void m() throws IOException {
      
      	}
      
      	public void m(int i) throws SQLException {
      
      	}
      
      }
      
      class B extends A {
      
      	// 子类不能抛出比父类更多的异常。
      	// 在方法重写的时候,子类中重写的方法抛出的异常不能超过父类。---要求的是编译时异常
      	public void m() throws EOFException, FileNotFoundException, NullPointerException {
      	}
      
      }

    八、finally关键字的运用

    1. 无论如何都会执行一次。往往用于一些资源需要回收等一系列 善后处理。
      public static void main(String[] args) {
      
      		try {
      
      			Scanner s = new Scanner(System.in);
      
      			System.out.println(s.nextInt() / s.nextInt());
      
      			s.close();
      
      		} catch (Exception e) {
      			e.printStackTrace();
      		} finally {
      			// 无论代码中出现异常与否,都会执行一次。
      			System.out.println("执行完毕");
      		}
      
      	}

    2. 无论try的代码中是否有异常,finally中的代码都会执行一次。
    3. finally执行在try中return和异常发生之前。
    4. 补充案例:
      public static void main(String[] args) {
      
      		System.out.println(m());
      
      	}
      
      	@SuppressWarnings("finally")
      	private static int m() {
      		try {
      			return 1;
      		} catch (Exception e) {
      			return 2;
      		} finally {
      			try {
      				return 4;
      			} finally {
      				return 5;
      			}
      		}
      
      	} // 结果是5
      
      public static void main(String[] args) {
      
      		System.out.println(m());
      
      	}
      
      	private static int m() {
      
      		int i = 5;
      
      		// 对于程序而言,是从上到下从左到右依次编译运行的。
      		try {
      			// return 5;-> i->6
      			return i++;
      		} finally {
      			// i = 6; -> 7
      			i++;
      			System.out.println("Finally:" + i);
      		}
      
      	}
      public static void main(String[] args) {
      
      		System.out.println(m());
      
      	}
      
      	public static Person m() {
      
      		Person p = new Person();
      
      		try {
      
      			p.setName("翠花");
      			p.setAge(16);
      
      			// return p; -> 实际上返回的是p的地址
      			return p;
      		} finally {
      
      			p = new Person();
      			p.setName("如花");
      			p.setAge(18);
      
      		}
      
      	}








    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值