Day_17异常机制

1.异常机制

1.1概述

异常是Java中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。

异常发生的原因有很多,比如

  1. 用户输入了非法数据
  2. 要打开的文件不存在
  3. 网络通信时连接中断
  4. JVM内存溢出
  5. 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。

1.2之前常见的异常

空指针

下标越界

栈内存溢出

类型转换异常

1.3

 1.4Error

1. 概念

系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。 

比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,JVM会选择终止程序

2.示例

//堆栈溢出错误
public class TestError {
    public static void recursionMethod() {
        recursionMethod();// 无限递归下去
    }
    public static void main(String[] args) {
        recursionMethod();
    }
}

报错信息:
Exception in thread "main" java.lang.StackOverflowError
    at com.TestError.recursionMethod(TestError.java:5)
    at com.TestError.recursionMethod(TestError.java:5)
    at com.TestError.recursionMethod(TestError.java:5)
    at com.TestError.recursionMethod(TestError.java:5)
    at com.TestError.recursionMethod(TestError.java:5)
    at com.TestError.recursionMethod(TestError.java:5)
... ...

1.5Exception

1.5.1是什么

Exception是所有异常类的父类。分为非RuntimeException和RuntimeException 。

  1. 非RuntimeException 
    指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常。
  2. RuntimeException 
    指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等。

 1.5.2常用方法

package com;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * 异常处理的两种方式 
 * 		1 throws  : 抛出异常,告诉调用处,这里可能有什么问题
 * 				如果你把异常抛给了调用处.那么调用处要么也抛出去,要么解决
 * 		2 try...catch... : 解决异常
 * 
 * 			
 
public class Exception_02 {
//	public static void main(String[] args) throws FileNotFoundException {
	public static void main(String[] args)  {
		// 打开资源文件
		try {
			FileInputStream fis = new FileInputStream("D:/xxx");
			System.out.println(123);
//		} catch (Exception e) {
		} catch (FileNotFoundException e) {
			// 打印错误的追踪栈帧,比较常用,适合程序员排错
			// e.printStackTrace();
			
			// 获取错误信息,适合响应给用户
			String msg = e.getMessage();
			System.out.println(msg);
		}
		System.out.println(456);
	}
}

1.5.3 Try...catch...

1.5.3.1第一种

try{
                 高风险代码;
              }catch(异常类型 变量){
                 解决方案;
              }

 

import java.io.FileNotFoundException;
import java.io.IOException;

public class Exception_03 {

}
class A{
	public void m1() throws IOException{
		
	}
}
class B extends A{
	@Override
	// 方法覆写,不能比原方法拥有更宽泛的异常
	//  抛出的异常类,可以是父类方法中抛出的类,也可以是对应的子类 , 但是不能是它的父类
	// 父类抛出一个异常A , 那么子类 要么还抛出A , 要么抛出A的子类, 要么不抛异常 , 但是不能是A的父类
	public void m1() throws FileNotFoundException{
	}
}

 

 1.5.3.2第二种

public static void main(String[] args) {
		try {
			FileInputStream fis = new FileInputStream("");
		} catch (FileNotFoundException e) {
			System.out.println("找不到文件");
		} catch (NullPointerException e) {
			System.out.println("不能为null");
		} catch (Exception e) {
			System.out.println("其他异常");
		}
	}

 1.5.3.3第三种

Java1.7新特性 自动关闭资源
 *
 * try{
 *         开启资源;
 * }catch(异常类型 变量){
 *         处理措施;
 * }finally{
 *         关闭资源
 * }
 *
 * -----
 *
 * try(开启资源){
 *         高风险代码;
 * }catch(异常类型 变量){
 *         处理措施;
 * }

public static void main(String[] args) {
		// 自动关闭资源
		try(FileInputStream fis = new FileInputStream("xxx");){
				// 操作
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

1.5.4覆写

1.5.5Throws

throws 抛出异常,并不会处理异常,是一种提醒机制
 如果你调用 的方法,抛出一个编译时异常,要么你就try..catch处理掉,要么你也抛出
         throws 是抛出异常,并不会解决异常,一般用于类库端(被调用的这个类)
                      而 try...catch... 是解决异常的,一般用于客户端(调用其他类的这个类,一般客户端都有main方法)
 

public static void main(String[] args) throws FileNotFoundException {
		m1();
	}

	public static void m1() throws FileNotFoundException {
		m2();
	}

	public static void m2() throws FileNotFoundException {
		m3();
	}

	public static void m3() throws FileNotFoundException {
		FileInputStream fis = new FileInputStream("xxx");
	}
// 抛异常 可以同时抛出多个,逗号隔开,没有先后顺序
	public static void main(String[] args) throws Exception,
			FileNotFoundException, IOException {

	}

1.5.6Finally

1.5.6.1finally : 必须执行的语句块 比如 打开的资源,需要关闭
 
 1 finally 不能单独出现,必须和try一起使用 或者和 try...catch...一起使用
 
 2 finally语句块 只有一种不执行的情况,那就是关闭虚拟机 System.exit(0);

public static void main(String[] args) {
		try {
			int a = 0;
			int b = 3;
			// 除数不能为0,会出错
			int c = b / a;
			System.out.println(c);
		} catch (Exception e) {
			e.printStackTrace();
			// 终止方法执行
			return;
			// System.exit(0);
		} finally {
			// 但是finally会执行
			System.out.println("2222");
		}
		// 执行不到,因为上面有return
		System.out.println("1111");
	}


 1.5.6.2注意

public static void main(String[] args) {
		int result = m1();
		// 11
		System.out.println(result);
	}

	public static int m1() {
		int i = 10;
		try {
			// 因为finally中有return,并且优先级是比较高的
			// 所以在编译的时候 就把这里的return去掉了,只有i++
			 return i++;
//			i++;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 11
			System.out.println(i+"------------");
		
		}
		return i;
	}

 

1.5.6.3应用场景

public static void main(String[] args) {
		FileInputStream fis = null;
		try {
			// 打开资源
			fis = new FileInputStream("xxx");
			// xx 操作
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			try {
				// 判断是否打开资源,如果打开 就关闭
				if (fis != null) {
					fis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

1.5.7Throw

异常源点

Throw new 异常类(错误信息);

参考自定义异常

1.5.8自定义异常类

1.5.8.1            1 继承一个已有的异常类
        判断你应该是运行是异常还是编译时异常,如果是运行时异常需要继承 RuntimeException 否则就继承Exception即可            

       一般情况下 我们写的 一定是 编译时异常
 2 公共的无参构造
 3 公共的有参构造,传入字符串,并在构造方法中把该字符串传递给父类

public class UserException extends Exception {
	public UserException() {

	}

	public UserException(String msg) {
		super(msg);
	}
}
public class Test {
	public static void main(String[] args) throws UserException {
		// 异常源
		throw new UserException("xxxxxxxx");
	}
}

1.5.8.2应用场景

public class UserService {
	public static void login(String username,String password) throws UserException{
		if (username.equals("admin")) {
			if (password.equals("root")) {
				// TODO 登陆成功
				// return "登陆成功";
			}else {
				// TODO 密码不正确
				// return "密码不正确" ;
				throw new UserException("密码不正确");
			}
		}else{
			// TODO 用户名不正确
			// return "用户名不正确";
			throw new UserException("用户名不正确");
		}
	}
}

 

需求 完成用户登陆
 * 
 * 1 如果用户名不是admin 则提示用户名不存在 2 如果密码不是root 则提示密码不正确
 * 
 * 客户端负责数据录入
 * 
 * service 负责 逻辑校验
 * 
 */
public class Client {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入用户名和密码 : ");
		String username = scanner.next();
		String password = scanner.next();
		// System.out.println(username+" : "+password);
		// String result = UserService.login(username, password);
		// if (result.equals("登陆成功")) {
		// System.out.println("欢迎回来");
		// }else{
		// System.out.println(result);
		// }
		try {
			UserService.login(username, password);
			System.out.println("登陆成功");
		} catch (UserException e) {
			// e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值