java编程基础总结——14.异常处理

一、异常:

    指的是程序运行过程中,因为用户的误操作、代码的BUG、
    等等一系列原因,引起的程序崩溃的现象,被称为异常

     崩溃:程序无法正常继续执行,在这行代码抛错,抛错操作系统解决不了,也抛了出去最终软       件退出(因为解决不了问题,无法正常运行)

例:

package com.openlab.day14;

import java.util.Scanner;

public class TestException01 {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入第一个数:");
		int num1 = input.nextInt();
		System.out.print("请输入第二个数:");
		int num2 = input.nextInt();
		int res = divide(num1, num2);
		System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
		input.close();
	}

	private static int divide(int num1, int num2) {
		int result = num1 / num2;
		return result;
	}

}

 

二、异常处理:

   解决掉异常的现象,让程序继续运行(不要崩溃退出)下去。
    程序容错能力提升!!!!程序就会越稳定!!!

java进行异常处理,有两种解决方案:
    |-- 抓捕异常【重点掌握】
    |-- 抛出异常

异常分类:
    1). 编译型异常:
        在源码编译阶段,直接抛出异常,这种异常必须要处理。
        不处理,则无法正常运行代码。

 例:

异常原因:路径可能不存在

    2). 运行时异常:
        在代码运行时,有可能出现的异常,被称为运行时异常

        一、异常   例就是运行时异常(除零异常)


1. 抓捕异常:

 针对于可能出现异常的代码,进行抓捕
    
    try {
        // 可能发生异常的代码

    } catch (Exception e) {
        // 如果出现了一次,代码会立刻进入catch中
        // 在这儿解决抓捕到的异常
    } finally {
        // 必须要执行的代码
    }

try {
    
    } catch(XxxException e) {
        // 异常处理
    } catch(XxxxException e) {
        // 异常处理
    } catch(Exception e) {
        // 异常处理
    } finally {
        // 必须要执行的代码

    }


如果使用抓捕异常,通过这种处理,程序即便是遇到了,也不崩溃!!!

package com.openlab.day14;

import java.io.File;
import java.util.Scanner;

public class TestException01 {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入第一个数:");
		int num1 = input.nextInt();
		System.out.print("请输入第二个数:");
		int num2 = input.nextInt();
		int res = divide(num1, num2);
		System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
		input.close();
	}

	private static int divide(int num1, int num2) {
		int result = 0;//局部变量必须初始化,无默认值。成员变量有默认值
		try {
			// 如果出现了错误,则立刻进入catch块
			result = num1 / num2;
		}catch(Exception e){
			//只有出现了异常,catch块中的代码才会执行
			System.out.println("出现了异常");
		}
		return result;
	}

}


1)try catch运行流程:

       出现异常的流程:try中出现异常代码之后的代码都不执行,立即跳入catch块,执行完之后再执行后继代码
      不出现异常的流程:只有catch块中的代码不执行。try执行完之后,跳过catch块,直接执行后继代码

package com.openlab.day14;

import java.io.File;
import java.util.Scanner;

public class TestException2 {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入第一个数:");
		int num1 = input.nextInt();
		System.out.print("请输入第二个数:");
		int num2 = input.nextInt();
		int res = divide(num1, num2);
		System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
		input.close();
	}

	private static int divide(int num1, int num2) {
		int result = 0;
		System.out.println(1);
		try {
			// 如果出现了错误,则立刻进入catch块
			System.out.println(2);
			result = num1 / num2;
			System.out.println(3);
		}catch(Exception e){
			System.out.println(4);
			//只有出现了异常,catch块中的代码才会执行
			System.out.println("出现了异常");
		}
		System.out.println(5);
		return result;
	}

}

不出现异常:

出现异常:

 

2)java中异常的继承关系:
    
    Throwable                异常的顶级类
        |-- Error            致命性的错误
        |-- Exception            常见的异常的父类
            |-- RuntimeException    运行时异常,只有运行时,才有可能出现异常
            
            其他的Exception的子类都是编译型异常,必须处理

 

 

3)多个异常的处理方案:
    最后其他异常可以用Exception e 来抓捕,运用了多态原理。所有异常都是Exception的子类,直接或者间接继承了Exception,根据多态原理,根据父类引用代指所有子类

 try {
    
    } catch(XxxException e) {
        // 异常处理
    } catch(XxxxException e) {
        // 异常处理
    } catch(Exception e) {
        // 异常处理
    }

private static int divide(int num1, int num2, Scanner input) {
		int result = 0;
		try {
			result = num1 / num2;
			input.nextInt();
		}catch(ArithmeticException e){
			e.printStackTrace();
			System.out.println("除数不能为零!!!");
		}catch(InputMismatchException e){
			e.printStackTrace();
			System.out.println("请输入整数!!!");
		}catch(Exception e){//
			e.printStackTrace();
			System.out.println("其他异常");
		}
		return result;
	}

4). finally关键字

         若都在try块中,关键代码在可能触发异常的代码之后,那么一旦触发异常,关键代码将不能被执行。因为异常,程序会直接跳到catch块中。所以java设计finally关键字。

 try {
        // 可能存在异常的代码
    } catch(XxxException e) {
        // 异常处理代码
    } [finally {
    
    
    }] // [ ] 表示可以有,可以没有

1). 把什么样的代码写在finally中?

    回收垃圾
    关闭IO流
    关闭数据库连接
    ……

    核心必须要执行代码

 2)finally块

        上断代码的关注点不是catch块,只是想执行try后执行finally

        在开发过程中,希望有的代码必须执行,但是不能保证一定执行,可能有异常等跳过代码,所以有这样一种结构。利用finally关键字的作用。

   try {
    
    } finally {
        // 将必须要执行的代码写在finally中!!!
    }


3). 注意:在开发过程中请注意,return关键字和finally关键字同时出现的情况,认真分析
    仔细考虑

finally 是在jvm层次执行的,不是在原码层次执行的。代码遇到return,,尤其是函数中,遇到return就会立即返回到调用的位置,在返回前,发现后面有finally,会将返回的状态保存在那里,之后开始执行finally,执行完返回。

package com.openlab.day14;

import java.io.IOException;

public class TestException4 {

	public static void main(String[] args) throws IOException {
		int res = say();
		System.out.println(res);
	}

	public static int say() {
		try {
			int a = 10;
			return a;
		} catch (Exception e) {
		} finally {
			System.out.println("这儿还会执行吗?");
		}
		return 0;
	}

}

面试题:下面代码的运行结果?

package com.openlab.day14;

import java.io.IOException;

public class TestException5 {

	public static void main(String[] args) throws IOException {

		int res = say();
		System.out.println(res);
	}

	public static int say() {
		int a = 10;
		int b = 20;
		try {
			b += a++;// b = 30  a = 11
			return b;
		} catch (Exception e) {

		} finally {
			a += 10;// a = 21
			b += 20;// b = 50
		}
		return a;
	}

}

finally在return之后执行,但是return的趋势已经形成,一旦return的趋势形成,会将要返回的值临时存储下来,等待后面执行finally之后再将它返回。虽然b = 50,a = 21,但是不影响将30return

2. 抛出异常:

         将异常交给调用者处理

        编程型异常,如果我们不想处理,可以直接抛给调用者,由调用者完成处理,调用者也不处理,会继续上抛,直到抛给main函数,main函数抛给jvm,jvm尝试处理,发现解决不了,就挂了

 

 

        由此看出,抛出异常并不是永久解决问题的方案,我们抛出异常原因:

        异常不一定会触发,尤其是编译型异常出现,懒得处理(如刚刚的文件例子,有路径异常就出现不了,出现不了就没有问题)

例:

package com.openlab.day14;

import java.io.File;
import java.io.IOException;

public class TestException4 {

	public static void main(String[] args) throws IOException  {
		String path = "c:/a.txt";
		creatFile02(path);
	}

	private static void creatFile02(String path) throws IOException {
		File file = new File(path);
		file.createNewFile();
	}

	private static void creatFile(String path) {
		try {
			File file = new File(path);
			file.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("创建失败");
		}
	}


}

三、自定义异常类:

        接触到的都是属于java官方提供的异常类,
        有时候自己设计异常类

    自定义异常类:定义一个普通的类,让该类成为成为Exception的子类或Exception类的孙子类

异常抛出:
    可以通过创建异常(系统或者自定义),来给调用者一个确切的错误信息
    调用者就可以通过抛出的信息做成对应的判断。       

        在自定义异常时,若继承Exception,做的是编译型异常,在编译阶段必须得处理,不建议使用编译型异常。建议使用运行时异常,简化写法

编译型异常例:

package com.openlab.day14;

public class MyException extends Exception{

	private static final long serialVersionUID = -5723348118187732441L;

	public MyException() {
		super();
		
	}

	public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
		
	}

	public MyException(String message) {
		super(message);
		
	}

	public MyException(Throwable cause) {
		super(cause);
		
	}

}
package com.openlab.day14;

public class Test02 {

	public static void main(String[] args) {

	}
	
	//登录功能
	//需要写 throws MyException 。抛出的是编译型异常,往出去抛还得在当前声明,所以不建议使用
	public void login(String username, String password) throws MyException {
		if(username.equals("admin") && password.equals("123456")) {
			System.out.println("登录成功");
		}else {
			//throws是放在方法上的,用来抛出不处理的异常,处理异常
			//throw是人为在底层向调用者抛出异常对象的,制造异常
			throw new MyException("对不起,用户名或者密码错误,请重新登录");
		}
	}

}

throws和throw区别:

        throws是放在方法上的,用来抛出不处理的异常,处理异常
        throw是人为在底层向调用者抛出异常对象的,制造异常

运行时异常例:

package com.openlab.day14;

/*
 * 在自定义异常时,建议使用运行时异常
 */
public class MyException extends RuntimeException{

	private static final long serialVersionUID = -5723348118187732441L;

	public MyException() {
		super();
		
	}

	public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
		
	}

	public MyException(String message) {
		super(message);
		
	}

	public MyException(Throwable cause) {
		super(cause);
		
	}

}
package com.openlab.day14;

public class Test02 {

	public static void main(String[] args) {
		try {
			new Test02().login("admin", "admin");
		}catch(MyException e) {
			//e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}
	
	//登录功能
	//编译型需要写 throws MyException 。抛出的是编译型异常,往出去抛还得在当前声明,所以不建议使用
	public void login(String username, String password)  {
		if(username.equals("admin") && password.equals("123456")) {
			System.out.println("登录成功");
		}else {
			//throws是放在方法上的,用来抛出不处理的异常,处理异常
			//throw是人为在底层向调用者抛出异常对象的,制造异常
			//自定义异常,可以向调用者传递需要的信息
			throw new MyException("对不起,用户名或者密码错误,请重新登录");
		}
	}

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值