异常

1、

/*
 * 异常即是一种意外,是程序运行过程中产生的一种突发(意外)
 * 事件,该事件会干扰程序的正常执行,打破程序的正常流程。
 * 
 * 当异常产生时,会创建一个相关异常类的对象,该对象含有异常的
 * 相关信息。
 * 异常产生时,会在异常的上下文中寻找异常处理程序,如果没有
 * 异常处理程序,则异常产生之后的语句将不会得到执行。该异常
 * 会向上传播(传播给方法的调用端)。如果传播到main方法里,还
 * 未处理该异常,则main方法会将异常传播给JVM,此时,整个
 * 线程终止执行。在控制台会打印出异常的相关信息与堆栈的调用
 * 轨迹。该轨迹是按照方法调用的逆序打印,即离异常发生地最近
 * 的方法会最先打印。
 */
package day12;

public class ExceptionTest {
	public static void main(String[] args) {
		a();
	}

	public static void a() {
		b();
	}

	public static void b() {
		c();
	}

	public static void c() {
		int x = 5;
		int y = 0;
		int z = x / y;
		System.out.println("x除以y的结果是:");
		System.out.println(z);
	}
}

  2、

异常可以分成以下三种:

      受检异常      运行时异常           错误

说明:运行时异常与错误统称为非受检异常。

当异常发生时,我可以采用两种方式进行处理:

 捕获异常

 抛出异常

说明:受检异常要求程序员在编译时显式处理,而非受检异常则不需要。

3、异常处理

/*
 * 异常处理程序(异常处理器)
 * try {
 * 		可能产生异常的程序
 * } catch (异常1) {
 * 		恢复措施
 * } catch (异常2) {
 * 		恢复措施
 * } ……
 * catch (异常n) {
 * 		恢复措施
 * }
 * 
 * try-catch的三种情况:
 * 1 try语句块中没有产生异常。此时try语句块全部执行完毕,
 * 之后执行try-catch之后的语句。
 * 2 try语句块中产生异常,catch捕获了该异常。
 * try中如果产生异常,则此时会创建一个相关异常类的对象,异常之后
 * 的语句将不会得到执行。程序会跳转到catch分支,从上到下依次使用
 * 异常类对象与每个catch中的异常类型进行匹配,哪一个catch分支
 * 匹配成功,则执行哪个catch语句块,此时异常被成功捕获。try-catch
 * 之后的语句正常执行。(最多只会执行一个catch分支)
 * 3 try语句块中产生异常,catch没有捕获该异常。
 * 当try中产生异常时,try异常之后的语句不会得到执行。程序
 * 跳转到catch分支进行异常匹配,没有匹配成功,则表示没有捕获
 * 该异常(该异常继续存在),则try-catch之后的语句不会得到
 * 执行,该异常会继续向上传播(传播给方法的调用端)。
 */
package day12;

public class Try {

	public static void main(String[] args) {
		try {
			int x = 1;
			// int y = 10;
			int y = 0;
			int z = x / y;
			// System.out.println(z);
			// String s = null;
			// s.length();
			// System.out.println("dd");
		} catch (ArithmeticException e) {
			// 打印异常错误的堆栈轨迹
			e.printStackTrace();
			// 打印异常的信息。
			// System.out.println(e.getMessage());
		}
		System.out.println("try-catch后的语句执行");
	}

}

  4、finally

/*
 * try-catch-finally
 * try-catch语句块可以同时使用finally。
 * catch与finally都是可选的。但是二者不能同时缺失。
 * finally的特征:
 * 不管try是否产生异常,也不管catch是否捕获了try中产生
 * 的异常,finally都将会得到执行。
 * 因为finally总是会得到执行(虚拟机退出的情况例外),所以
 * 我们在finally语句块中进行资源的释放是非常合适的。
 * 
 * finally中的返回值会镇压try中的返回值。
 */
package day12;

public class Finally {
	public static void main(String[] args) {
		try {
			// System.out.println("没有产生异常");
			// String s = null;
			// s.length();
			// System.out.println(5 / 0);
			// 回收程序
		} catch (NullPointerException e) {
			// e.printStackTrace();
		} finally {
			// System.out.println("finally执行了");
		}

		// for (int i = 0; i < 10; i++) {
		// try {
		// break;
		// } finally {
		// System.out.println("finally执行了");
		// }
		// }
		// f();
		// try {
		// // 退出虚拟机
		// System.exit(0);
		// } finally {
		// System.out.println("finally执行了");
		// }
		System.out.println(g());
	}

	public static void f() {
		try {
			return;
		} finally {
			System.out.println("finally执行了");
		}
	}

	// 返回的是fianlly中的return值。
	public static int g() {
		try {
			return 1;
		} finally {
			return 2;
		}
	}
}

  5、

/*
 * 捕获异常时,如果多个catch捕获的异常类型存在父子关系,
 * 则需要将子类型方法前面,父类型放在后面。因为子类型能够
 * 捕获的,父类型都能够捕获,如果父类型的catch放在前面,
 * 则子类型的catch永远没有机会得到执行。
 */
package day12;

public class CatchOrder {

	public static void main(String[] args) {
		try {

		} catch (NullPointerException e) {

		} catch (RuntimeException e) {

		} catch (Exception e) {

		}
		/*
		 * try {
		 * 
		 * } catch(Exception e) {
		 * 
		 * } catch (RuntimeException e) { //永远没有机会得到执行 }
		 */
	}

}

  6、多重捕获异常

/*
 * 多重捕获异常
 * 
 * 当try语句块中,可能会产生多个异常,而多个异常的处理方式
 * 又完全相同时,我们就可以使用多重捕获异常。
 * 注意:不要使用多个异常的父类来代替多重捕获异常,因为父类
 * 会捕获更多的异常(我们意料之外的异常),这可能会隐藏掩盖
 * 我们程序的漏洞。
 * 
 * 当使用多重异常捕获时,catch捕获异常的参数将隐式使用final
 * 来修饰。
 */
package day12;

public class MultiCatch {

	public static void main(String[] args) {
		try {
			// 可能产生异常的代码
		} catch (ArithmeticException e) {
			e.printStackTrace();
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
		// 多重捕获
		try {
			// String s = null;
			// s.length();
			// System.out.println(1 / 0);
		} catch (ArithmeticException | NullPointerException e) {
			e.printStackTrace();
			// e = null;
		}

		try {
			String s = null;
			s.length();
			// System.out.println(1 / 0);
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

}

  7、throws 异常列表

/*
 * throws 异常列表
 * 
 * 如果一个方法中可能会抛出受检异常,则要求该异常必须
 * 同时声明在方法的异常列表中。对于非受检异常(运行时
 * 异常与错误),则不要求声明在方法的异常列表中。
 * 
 * 异常分为三种:
 * 1 受检异常(编译时异常)
 * 2 运行时异常
 * 3 错误
 * 运行时异常和错误统称为非受检异常。
 * 
 * 受检异常继承Exception类或其子类。
 * (不包括RuntimeException或其子类)
 * 运行时异常继承RuntimeException或其子类。
 * 错误继承Error类或其子类。
 * 
 * 受检异常与非受检异常的区别:
 * 受检异常必须在编译期间就需要明确对其进行处理,
 * 而非受检异常则不需要。
 */
package day12;

import java.io.FileNotFoundException;

public class Throws {

	public static void main(String[] args) {

	}

	public void f(int x, int y) throws FileNotFoundException {
		if (x < 0) {
			throw new NullPointerException();
		}

		if (y < 0) {
			throw new FileNotFoundException();
		}
	}

	// 该方法不会抛出FileNotFoundException(受检异常)
	public void g(int x) {
		// try {
		// if (x < 0) {
		// throw new FileNotFoundException();
		// }
		// } catch(FileNotFoundException e) { }
	}

}

  8、方法重写的第五条

/*
 * 方法重写的第五条要求:
 * 子类重写父类的方法,则子类方法不能比父类方法抛出更多
 * 的受检异常。(只能与父类相同,或者是父类抛出受检异常的
 * 子类异常)。对于非受检异常,则不受限制。
 */
package day12;

public class Override5 {
	public static void main(String[] args) {
		Override5 o = new Override5();
		o.use(new WhiteHorse());
	}

	public void use(Horse h) {
		h.run();
	}

	/*
	 * public int x() { throw new NullPointerException(); }
	 */
}

class Horse {
	public void run() {

	}
}

class WhiteHorse extends Horse {
	// 错误,子类方法比父类方法抛出了更多的受检异常。
	/*
	 * @Override public void run() throws Exception {
	 * 
	 * }
	 */

	@Override
	public void run() throws NullPointerException, IllegalArgumentException {

	}
}

  9、手动抛出异常

/*
 * 手动抛出异常 throw
 */
package day12;

public class Throw {
	public static void main(String[] args) {
		Throw t = new Throw();
		t.deal(-1);
		
	}

	public void deal(int age) {
		if (age <= 0) {
			throw new IllegalArgumentException("年龄必须大于0!输入年龄为:" + age);
		}
		System.out.println("执行了吗?");
		// 对年龄进行处理
	}
}

  10、自定义异常

/*
 * 自定义异常
 * 为什么要使用自定义异常?
 * 1 Java类库提供的异常类不能满足所有人的需要。
 * 2 自定义异常可以令我们快速定位问题。
 * 
 * 按照惯例,自定义异常名使用Exception进行结尾。
 */
package day12;

public class SelfException {
	public void use() {
		SelfException s = new SelfException();
		//s.deal(-1);
		try {
			s.deal(-1);
		} catch (NegtiveAgeException e) {
			System.out.println("进行异常的处理");
		}
	}

	public void deal(int age) {
		if (age <= 0) {
			throw new NegtiveAgeException("年龄为负!" + age);
		}
		System.out.println("年龄合理,进行处理。");
	}
}

class NegtiveAgeException extends RuntimeException {
	public NegtiveAgeException(String s) {
		super(s);
	}

	public NegtiveAgeException() {
		this("年龄为负数,请输入核对!");
	}
}

  11、异常优势:

使用异常具有如下优势:
 可以将正常的代码与异常处理的代码相分离。
 可以将异常信息沿着方法调用轨迹向上传播。
 异常具有明确的类型与继承体系, 便于分类处理。

  补充:

1、捕获异常

使用try(尝试着)去执行可能产生异常的程序,一旦异常发
生,系统会自动创建一个相应的异常类对象,同时终止try
执行( try语句块异常产生位置之后的代码将不会执行)。
一旦产生异常,将会从上到下去匹配catch中异常类,一旦匹
配成功,则异常对象就会传递给catch参数,执行相应catch
语句块。如果没有匹配成功,则该异常会继续向上抛出给方
法调用端。
catch语句块最多只会执行一个。如果所有方法中都没有合适
的异常处理器,则当前线程终止。

无论try是否抛出异常,也无论catch是否捕获异常, finally
语句块都将在trycatch执行后执行。
catch捕获的异常类型必须是Throwable类型或其子类型。
finally是可选的。 catch也是可选的,但catchfinally不能
同时为空。

2、

常见异常:
1:非受检异常
NullPointerException,ClassCastException,ArrayIndexsOutOfBoundsException,ArithmeticException(算术异常,除0溢出)
2)受检:Exception,FileNotFoundException,IOException,SQLException.

原文地址:https://www.cnblogs.com/liuwei6/p/6572729.html