异常

  • 异常的概念: 程序出现了不正常的情况
  • 异常本质就是Java当中对可能出现的问题进行描述的一种对象体现。
  • 简单来说:异常本质就是异常描述的对象体现
  • 异常的分类:
  • 异常(Exception)
  • 编译时异常 (受检异常): 在程序的编译时期就出问题,这个是可以提前处理的
  • 不是继承自RuntimeException的Exception的子类都成为编译时期异常。
  • 运行时异常 (非受检异常): 在程序运行时期出现问题,这个一般都是代码不够健壮,不够严谨,也是可以处理的
  • RuntimeException及其所有子类都是运行时期异常。
  • 错误(Error): 是无法避免的,也是程序员无法解决的 StackOverflowError
  • 异常目的:能够保证程序继续执行 ArithmeticException
package com.sxt.exceptiondemo;

/*
 * 生活的异常
 * 
 * 班长开新买的宝马来上学
 * 
 *  出门前 (编译时期)
 *  班长的妈妈说 开车一定要加满油
 *  班长的爸爸说 注意脚下的路
 *  姐姐说 小心碰瓷
 *  
 *  在路上 (运行时期)	
 *  被车撞
 *  漏油
 *  路上看到柳岩的演唱会
 *  
 *  到学校门口  地震了
 *  
 *  异常的概念: 程序出现了不正常的情况
 *  异常本质就是Java当中对可能出现的问题进行描述的一种对象体现。
 *  简单来说:异常本质就是异常描述的对象体现
 *  
 *  异常的分类
 *   异常(Exception) 
 *  	编译时异常 (受检异常): 在程序的编译时期就出问题,这个是可以提前处理的
 *  	不是继承自RuntimeException的Exception的子类都成为编译时期异常。
 *  	运行时异常 (非受检异常): 在程序运行时期出现问题,这个一般都是代码不够健壮,不够严谨,也是可以处理的
 *  	RuntimeException及其所有子类都是运行时期异常。
 *   错误(Error): 是无法避免的,也是程序员无法解决的 StackOverflowError
 *   	
 *  异常目的:能够保证程序继续执行 ArithmeticException
 */
public class ExceptionDemo01 {
	public static void main(String[] args) {
		System.out.println("吃鸡开始");
		int a = 10;
		int b = 0;
		System.out.println(a/b);
		System.out.println("今晚吃鸡,大吉大利");
	}
	
//	public static void show() {
//		System.out.println("show");
//		show();
//	}
}
  • 异常处理

  • 为什么需要处理异常? – 保证程序继续执行

  • 如果我们不处理异常,jvm是如何处理异常的

  • JVM异常处理机制

  • 1.打印错误信息

  • Exception in thread “main” java.lang.ArithmeticException: / by zero
    at com.sxt.exceptiondemo.ExceptionDemo02.main(ExceptionDemo02.java:16)
    a.异常名称
    b.异常信息
    c.异常所发生的方法
    d.异常的行号

  • 2.将虚拟机终止

  • JVM处理异常的方式不能够满足我们的需求

  • 所以我们需要自己来处理异常

  • 如何来处理异常?

  • 异常处理的格式:

  • 方式一: try…catch…finally

  • 方式二: throws

  • 方式一处理异常:

try {
 		// 放置可能出现问题的代码,这里代码越少越好
 } catch(异常类名 异常对象){
 		// 处理异常的代码
 } catch(异常类名 异常对象){
 		// 处理异常的代码
 } ...catch(异常类名 异常对象) {
 		// 处理异常的代码
 } finally {
 		// 释放资源的代码
 }
  • 注意:
  • 1.try不可以独立存在,try-catch,try-catch-finally,try…finally是可以的
  • 2.try中如果出现了问题,抛出异常对象,不会执行try块中后面的代码
  • 3.多个catch块只能够执行一个
  • 异常处理的执行流程:
  • 1.程序执行到47行
  • 2.系统会抛出一个异常对象
  •  本质: 
     ArithmeticException ae = new ArithmeticException();
     throw ae;
    
  • 3.无论47行下面有多少代码都不会被执行,程序进入catch块异常捕获
  • 4.依次和每一个catch进行匹配
    匹配成功: 程序执行catch块代码,程序继续执行
    匹配失败: 交给JVM处理
  • 标准的异常处理方式:
  • 1.能够显示捕获的异常就显示声明捕获
  • 2.就算程序异常处理的很全面还是有可能有其他异常,所以在最后面可以使用Exception父类异常做统一捕获
package com.sxt.exceptiondemo;

/*
 * 面试题: 代码实现虚拟机处理异常的过程
 */
public class ExceptionDemo02 {
	public static void main(String[] args) {
//		System.out.println("第一步");
//		int a = 10;
//		int b = 0;
//		try {
//			System.out.println(a/b); // throw new ArithmeticException();
//			System.out.println("我执行了吗?");
//		} catch(NullPointerException ae) { 
//			// ArithmeticException ae = new ArithmeticException();
//			System.out.println("出问题了!!!");
//		}
//		System.out.println("第二步");
		
		System.out.println("第一步");
		int a = 10;
		int b = 0;
		String s = null;
		int[] arr = new int[3];
		try {
//			System.out.println(a/b); // throw new ArithmeticException();
//			System.out.println(s.equals("null"));
//			System.out.println(arr[-1]);
			Object obj = new Integer("100");
			System.out.println((String)obj);
			System.out.println("我执行了吗?");
		} catch(ArithmeticException ae) { 
			// ArithmeticException ae = new ArithmeticException();
			System.out.println("算数异常");
		} catch (NullPointerException ne) {
			System.out.println("空指针异常");
		} catch (ArrayIndexOutOfBoundsException aioobe) {
			System.out.println("数组越界异常");
		} catch (Exception e) {
			System.out.println("出问题了!!!");
		}
		System.out.println("第二步");

	}
}
  • Throwable类
  • Throwable fillInStackTrace()
    填写执行堆栈跟踪。
  • String getLocalizedMessage()
    创建此可抛出的本地化描述。
  • String getMessage()
    返回此throwable的详细消息字符串。
  • StackTraceElement[] getStackTrace()
    提供对 printStackTrace()打印的堆栈跟踪信息的 编程访问 。
  • void printStackTrace()
    将此throwable和其追溯打印到标准错误流。
  • void printStackTrace(PrintStream s)
    将此throwable和其追溯打印到指定的打印流。
  • void printStackTrace(PrintWriter s)
    将此throwable和其追溯打印到指定的打印作者。
  • void setStackTrace(StackTraceElement[] stackTrace)
    设置将被返回的堆栈微量元素 getStackTrace()和由印刷 printStackTrace()和相关方法。
  • String toString()
    返回此可抛出的简短描述。
package com.sxt.exceptiondemo;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;

/*
 * 面试题: 代码实现虚拟机处理异常的过程  
 */
public class ExceptionDemo03 {
	public static void main(String[] args) throws FileNotFoundException {
//		Throwable t = new NullPointerException("空指针异常");
//		System.out.println(t); // java.lang.NullPointerException: 空指针异常
//		
//		// StackTraceElement[] getStackTrace() 
//		StackTraceElement[] stackTraces = t.getStackTrace();
//		System.out.println(stackTraces.length);
//		for (StackTraceElement element : stackTraces) {
//			String fileName = element.getFileName();
//			boolean nativeMethod = element.isNativeMethod();
//			String methodName = element.getMethodName();
//			String className = element.getClassName();
//			int lineNumber = element.getLineNumber();
//			
//			System.out.println(fileName + "|" + methodName 
//					+ "|" + nativeMethod + "|" + className + "|" + lineNumber);
//		}
		
		show();
//		void printStackTrace() 
//		t.printStackTrace();
		
		/*
		 * 第一步
		 * Exception in thread "main" 
			java.lang.ArithmeticException: / by zero
				at com.sxt.exceptiondemo.ExceptionDemo03.main(ExceptionDemo03.java:52)
		 */
		/*System.out.println("第一步");
		int a = 10;
		int b = 0;
		try {
			System.out.println(a/b); 
		} catch (Exception e) {
			StackTraceElement[] stackTraces = e.getStackTrace();
			String methodName = stackTraces[0].getMethodName();
			String className = stackTraces[0].getClassName();
			String fileName = stackTraces[0].getFileName();
			int lineNumber = stackTraces[0].getLineNumber();
			System.err.printf("Exception in thread \"%s\"" + 
					"%s\r\n" + 
					"	at %s.%s(%s:%d)", methodName, e.toString(), 
					className, methodName,fileName,lineNumber);
			// void printStackTrace(PrintWriter s) 
			
			String exceptionMessage = String.format("Exception in thread \"%s\"" + 
					"%s\r\n" + 
					"	at %s.%s(%s:%d)", methodName, e.toString(), 
					className, methodName,fileName,lineNumber);
			PrintWriter s = new PrintWriter(new FileOutputStream("Console"), true);
			s.println(exceptionMessage);
			e.printStackTrace(s);
			System.exit(1);
		}*/
		
//		System.out.println("第二步");
	}
	
	public static void show() {
		method();
	}
	
	public static void method() {
		Throwable t = new NullPointerException("空指针异常");
		StackTraceElement[] stackTraces = t.getStackTrace();
		System.out.println(stackTraces.length);
		for (StackTraceElement element : stackTraces) {
			String fileName = element.getFileName();
			boolean nativeMethod = element.isNativeMethod();
			String methodName = element.getMethodName();
			String className = element.getClassName();
			int lineNumber = element.getLineNumber();
			
			System.out.println(fileName + "|" + methodName 
					+ "|" + nativeMethod + "|" + className + "|" + lineNumber);
		}
	}
}
  • 编译时异常的处理 以及 如何来查看异常

  • 处理方式: Ctrl+1 自动修复

  • 如何来查看异常

  • 查看错误: 从下往上看,先看你能够看懂的,再看源码里面的

package com.sxt.exceptiondemo;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/*
 * 编译时异常的处理 以及 如何来查看异常
 * 
 * 处理方式: Ctrl+1 自动修复
 * 
 * 如何来查看异常
 * 查看错误: 从下往上看,先看你能够看懂的,再看源码里面的
 */
public class ExceptionDemo04 {
	public static void main(String[] args) {
		System.out.println("main start");
		exception();
		System.out.println("main end");
	}

	private static void exception() {
		System.out.println("exception first");
		method();
		System.out.println("exception last");
	}

	private static void method() {
		String dataStr = "2019/01/26 14:08:20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss"); // throw new ParseException("Unparseable date: "2019/01/26 14:08:20"");
		try {
			sdf.parse(dataStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
}
  • 为什么有了try…catch处理异常还需要学习throws处理异常?

  • 有的时候可能我们没有办法处理,或者我压根就不想处理,又或者我压根没有权限处理,这个时候可以将异常抛出,抛给调用者

  • throws关键字概述
    在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用者进行处理。

  • throws格式

	[修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2....]{
   }

注意:

  • 1.如果抛出的是运行时异常,可以处理,也可以不处理,但是不能够抛给主方法,因为主方法是jvm调用,jvm的处理方式就是终止程序
  • 2.如果抛出的是编译时异常,必须处理,处理方式既可以是try catch也可以是throws,但是不能够抛给主方法
  • 3.重写一个方法时,它所声明的异常范围不能被扩大。
  • 4.异常处理如果是平级关系的异常,可以并行处理 ArithmeticException|NullPointerException|ClassCastException e
package com.sxt.exceptiondemo;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/*
 * 为什么有了try...catch处理异常还需要学习throws处理异常?
 * 	有的时候可能我们没有办法处理,或者我压根就不想处理,又或者我压根没有权限处理,这个时候可以将异常抛出,抛给调用者
 * 
 * throws关键字概述
	在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用者进行处理。
	
 * throws格式
 * [修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2....]{
   }

	注意:
		1.如果抛出的是运行时异常,可以处理,也可以不处理,但是不能够抛给主方法,因为主方法是jvm调用,jvm的处理方式就是终止程序
		2.如果抛出的是编译时异常,必须处理,处理方式既可以是try catch也可以是throws,但是不能够抛给主方法
		3.重写一个方法时,它所声明的异常范围不能被扩大。
		4.异常处理如果是平级关系的异常,可以并行处理 ArithmeticException|NullPointerException|ClassCastException e
 */
public class ExceptionDemo05 {
	public static void main(String[] args) throws ArithmeticException, ParseException {
//		System.out.println("start");
//		show();
//		System.out.println("end");
		
		try {
			Demo.method();
		} catch (ArithmeticException|NullPointerException|ClassCastException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public static void show() throws ArithmeticException, ParseException {
//		method();
//		test();
	}
	
	public static void method() throws ArithmeticException {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}
	
	public static void test() throws ParseException, Exception, Throwable {
		String dataStr = "2019/01/26 14:08:20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss"); // throw new ParseException("Unparseable date: "2019/01/26 14:08:20"");
		sdf.parse(dataStr);
	}
	
}

class Father {
	public void method() throws Exception {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}
}

class Son extends Father {
	@Override
	public void method() throws NullPointerException, ArithmeticException, ParseException {
	}
}

class Demo {
	public static void method() throws ArithmeticException, NullPointerException, ClassCastException {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}
}
  • throw关键字

  • 格式: throw 异常对象

  • 面试题: throw和throws的区别

  • 1.throws出现在方法的声明上,throw出现在方法体内

  • 2.throws表示一种异常出现的可能性,而throw表示一定出现了异常

  • 3.throws可以声明多个,但是throw只能够抛出一个对象

  • 4.throws声明的是异常类,而throw抛出的是异常对象

package com.sxt.exceptiondemo;

import java.util.Scanner;

/*
 * throw关键字
 * 
 * 格式: throw 异常对象
 * 
 * 面试题: throw和throws的区别
 * 1.throws出现在方法的声明上,throw出现在方法体内
 * 2.throws表示一种异常出现的可能性,而throw表示一定出现了异常
 * 3.throws可以声明多个,但是throw只能够抛出一个对象
 * 4.throws声明的是异常类,而throw抛出的是异常对象
 */
public class ExceptionDemo06 {
	public static void main(String[] args) {
		try {
			method();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println("over");
	}
	
	public static void method() throws ArithmeticException {
		Scanner input = new Scanner(System.in);
		int a = 10;
		int b = input.nextInt();
		if (b == 0) {
			throw new ArithmeticException("除数不能为0");
		}
		System.out.println(a / b);
		
	}
}
finally关键字
try {
 
 } catch(异常类 异常对象){
 
 } finally {
		这里的代码一定会被执行,除非碰到系统退出  System.exit(0)或者 Runtime.getRuntime().exit(0);
 		一般用来释放资源,比如说数据库的连接,IO流的输入输出对象的关闭
}
package com.sxt.exceptiondemo;

import java.util.Scanner;

/*
 * finally关键字
 * 
 * try {
 * 
 * } catch(异常类 异常对象){
 * 
 * } finally {
 * 		这里的代码一定会被执行,除非碰到系统退出  System.exit(0)或者 Runtime.getRuntime().exit(0);
 * 		一般用来释放资源,比如说数据库的连接,IO流的输入输出对象的关闭
 * }
 * 
 * finally final finallize的区别?
 * 
 * finally和return?
 */
public class ExceptionDemo07 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String line = input.nextLine();
		System.out.println(line);
//		input.close();
		try {
			int a = 10;
			int b = 0;
			System.out.println(a / b);
			System.out.println("try 我执行了吗");
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("catch 我执行了吗");
//			return;
//			System.exit(0);
//			Runtime.getRuntime().exit(0);
		} finally {
			System.out.println("finally 我执行了吗");
			input.close();
		}
		
	}
	
}
  • finally碰到return

  • finally一定会执行

  • 执行顺序?

  • 在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。

  • 在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,

  • 因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。

package com.sxt.exceptiondemo;

 
public class ExceptionDemo08 {
	public static void main(String[] args) {

		System.out.println(test()); // 3
	}

	public static int test() {
		int x = 1;
		try {
			x++; // 2
			return x; // return 2;
		} finally {
			++x; // 3
			System.out.println(x); // 3 
		}
	}
}

异常: 本质就是错误信息在Java当中的一个对象体现

  • Java提供了很多的异常,但是还是不能够满足我们开发的需求,既然异常本质仅仅是一个描述,那么我们

  • 完全可以自己来描述我们所谓的错误,并且编写一个类来表达我们的错误描述

  • 自定义一个异常,要求考试成绩必须在0-100之间,如果不在这个范围内,抛出异常。

  • 自定义异常的步骤
    1.自定义异常必须是Throwable的子类
    2.书写一个类继承Exception
    3.书写两个构造方法
    a.无参构造方法 (没有带错误描述)
    b.带参构造方法 (带错误描述)

package com.sxt.exceptiondemo;

import java.util.Scanner;

public class ExceptionDemo10 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入分数:");
		double score = input.nextDouble();
		Teacher t = new Teacher();
		
		try {
			System.out.println(t.isBetween0To100(score) ? "分数合法" : "分数不合法");
		} catch (ScoreException e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				input.close();
			}
		}
		
		System.out.println("分数批改完毕!!!");
		
	}
}

class Teacher {
	public boolean isBetween0To100(double score) throws ScoreException {
		if (score >= 0 && score <= 100) {
			return true;
		} else {
			throw new ScoreException("分数必须在0~100分之间!!!");
		}
	}
}

class ScoreException extends Exception {
	private static final long serialVersionUID = -1989349702073875392L;

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

1、自定义一个异常判断身份证号是否合法
运行结果:
输入身份证号码:
12365
1.可以是15位或者18位的数字
2.15位纯数字
3.18位最后一位是有X的,最后一位是确认码,0-9和X或者x.
异常:身份证号码不合法

package com.sxt.exceptiondemo;

import java.util.Scanner;


public class ExceptionDemo11 {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		try {
			System.out.println(Test.checkIDCard(new Scanner(System.in).next()) ? "合法身份证" : "非法身份证");
		} catch (IDCardException e) {
			e.printStackTrace();
		}
		System.out.println("身份证检查完毕");
	}
}

class Test {
	public static boolean checkIDCard(String idCard) throws IDCardException {
		if (idCard.matches("\\d{15}|\\d{17}[\\dxX]")) {
			return true;
		} else {
			throw new IDCardException("非法身份证!!!");
		}
	}
}

class IDCardException extends RuntimeException {

	private static final long serialVersionUID = 392084157998377850L;

	public IDCardException() {
	}

	public IDCardException(String message) {
		super(message);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值