day21 异常(一)

我们写程序,关注的是发生异常后如何处理

所有的异常和错误的父类是Throwble>object

有两个子类:一个是Error(了解) 一个是Exception

Exception中分为两派,一个是检查异常(Runtimelei),一个是运行时异常

检查异常在我们的代码编写阶段必须处理,否则编译不通过

运行时异常不是必须处理

基本语法 重点

try...catch(异常类型 e)...

try括住可能出异常的代码块,catch 捕获异常 使用异常处理可以保证我们的代码正常执行

public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		int a = 10;
		int b = 0;

		/*
		 * if (b == 0) { System.out.println("除数不能为0"); } else { int v = a / b;
		 * System.out.println(v); }
		 */

		try {
			int v = a / b;
			System.out.println(v);
		} catch (ArithmeticException e) {
			// 打印异常的跟踪信息
			e.printStackTrace();
			// 异常信息
			// System.out.println(e.getMessage());
			System.out.println("除数不能为0");
		}
		System.out.println("运算正常");

	}

}

try-catch-finally 重点

不管是否有异常,finally里的代码都会执行(除非使用System.exit(),非0表示非正常退出,1表示某种情况,2表示某种情况 )

面试题:finally唯一不执行的情况是什么?

finally不执行的情况就是在finally之前退出虚拟机

System.exit() 非0表示非正常退出,1表示某种情况,2表示某种情况

目前来说,没有区别,都是退出

面试题:try-catch-finally中都有return的情况怎么执行?(或者问try-catch-finally中存在return语句,是否还执行finally?如果执行,请说出执行顺序。) 1. finally中不要对返回值做操作

如果做了操作,也依然按照try中的返回值

2.

在catch块中也不推荐对返回值的做操作

但是在报错的情况下,如果在try返回值之前报错,那么就是将遵照最终的返回值,也就是方法最后的返回值

总结:

try catch finally 中如果都存在return,那么将使用最终finally中的return作为返回值

不要在finally和catch中加return,切记

try-catch-finally结构中try语句是必须的,catch和finally语句均可选,但两者至少出现一个

public class App2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Student stu = new Student(10, "zhangsan", 20);
		
		stu.setName(null);
		
		// 进行io操作、数据库的操作,一般在finally里做一些特定操作,比如关闭连接等等
		try {
			
			if(stu.getName().equals("zhangsan")) {
				System.out.println("欢迎zhangsan");
			}
			// 退出程序
			// System.exit(-1);
			return;
		}catch(NullPointerException e) {
			// NPE
			System.out.println("空指针异常");
			return;
		} finally {
			System.out.println("不管怎么执行,都会回到我的怀抱");
		}
		// System.out.println("hahaha");
	}

}

常见异常

Exception的子类:受检异常(必须处理的异常)、运行时异常

Exception 异常层次结构的父类 ArithmeticException算术错误情形,如以零作除数 ArrayIndexOutOfBoundsException数组下标越界 NullPointerException尝试访问 null 对象成员 ClassNotFoundException不能加载所需的类 IllegalArgumentException方法接收到非法参数 ClassCastException对象强制类型转换出错 NumberFormatException数字格式转换异常,如把"abc"转换成数字

多重catch块处理

先子类后父类

异常的匹配的顺序从上到下

一般建议增加catch(Exception e) {}

public class App3 {

	public static void main(String[] args) {

		try {
			int a = 10;
			int b = 5;
			int v = a / b;

			String name = "zhagnsan";
			if (name.equals("zhangsan")) {
				System.out.println("zhangsan");
			} else {
				System.out.println("gousheng");
			}
			
			Integer.parseInt("abc");
			
		} catch (ArithmeticException e) {
			System.out.println("除数不能为0");
		} catch(NullPointerException e) {
			System.out.println("空指针异常");
		} catch(Exception e) {
			System.out.println("未知异常,请联系管理员");
		}

	}
}

声明异常 重点

throws

通过在方法后面声明异常进行抛出

方法后可以声明多个异常,多个异常之前用逗号分隔

main方法后也可以使用throws,抛出的异常交给JVM处理

throws Exception 表示当前方法有可能会出现一个??异常,通知调用者去处理

或者继续抛出

throwthrows
生成并抛出异常声明方法内跑出来异常
位于方法的内部必须跟在方法参数列表后面,不能单独使用
抛出一个异常对象,且只能是一个声明抛出异常类型,可以跟多个异常

public class App5 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

//		try {
//			int v = div(10, 4);
//			System.out.println(v);
//			
//			sub(null);
//		} catch (ArithmeticException e) {
//			System.out.println("算数异常");
//		} catch (Exception e) {
//			
//		}
		
		sub(null);

	}

	public static int div(int a, int b) throws ArithmeticException {
		int v = a / b;
		return v;
	}
	
	public static void sub(String str) throws Exception {
		String substring = str.substring(2);
		System.out.println(substring);
	}
	
	public static void oper(String str) throws ArithmeticException, IndexOutOfBoundsException {
		String substring = str.substring(2);
		System.out.println(substring);
	}

}

 

抛出异常 重点

throw

通过创建异常对象进行抛出,一次只能抛出一个异常

一般可以抛出运行时异常

借助throw,可以中断业务的执行,并不一定抛出的都是官方定义的具体异常

public class App6 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			login("admin", "123456");
		} catch (RuntimeException e) {
			// geMessage 获取异常信息
			System.out.println(e.getMessage());
		}

	}

	/**
	 * 登录方法
	 * 
	 * @param username
	 * @param password
	 */
	public static void login(String username, String password) {
		if (!username.equals("admin")) {
			// 后续的逻辑终止执行, 参数表示具体的异常信息
			throw new RuntimeException("用户名错误");
		}
		if (!password.equals("123456")) {
			throw new RuntimeException("密码错误");
		}
		System.out.println("欢迎登录");
	}

}

自定义异常

自定义类继承throwable/Exception/RuntimeException

一般在自定义异常类里,根据业务需要,增加一个额外的属性

jdk中没有给我们提供一些具体的异常类,比如年龄,性别异常

所以我们需要按自己要求来自定义异常

1.继承异常父类

2.调用父类的构造方法,重新给message属性赋值,这个属性用于打印提示信息的

3直接抛出我们定义好的异常对象即可

异常处理原则

异常处理与性能

异常只能用于非正常情况

不要将过于庞大的代码放在try中

在catch中指定具体的异常类型

需要对捕获的异常做处理

总结

•异常分为Checked异常和运行时异常

•Checked异常必须捕获或者声明抛出

•运行时异常不要求必须捕获或者声明抛出

•try-catch-finally中存在return语句的执行顺序(面试题)

•finally块中语句不执行的情况(面试题)

•throw和throws关键字的区别(面试题)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值