认识异常对程序的影响
异常会造成一个完整的程序在执行过程中中断。
我们来看一下例子:
[完整的程序]
public class Test{
public static void main(String[] args) {
System.out.println("执行程序");
System.out.println("执行过程:"+20*3);
System.out.println("执行完成");
}
}
执行结果:
执行程序
执行过程:60
执行完成
当没有异常的情况程序会从头到尾的执行完毕
[异常的程序]
public class Test{
public static void main(String[] args) {
System.out.println("执行程序");
System.out.println("执行过程:"+20/0);
System.out.println("执行完成");
}
}
执行结果:
执行程序
Exception in thread "main" java.lang.ArithmeticException: / by zero
at amazon.Test.main(Test.java:7)
当程序中有异常的时候那么不会执行全部,会在异常的地方中断此次执行。
处理异常
一般我们处理异常都是用try…catch…finally来抛出异常
- try块:放可能会触发异常的代码
- catch块:当try块触发异常会到catch里面处理
- finally块:不管有没有异常都会执行里面的代码
搭配,try…catch…finally有三种搭配模式
//第一种
try{
}catch(异常类型 异常对象){
//异常处理
}finally{
}
//第二种
try{
}finally{
}
//第三种
try{
}catch(异常类型 异常对象){
//异常处理
}
try块必须要有的
例子:比如我们处理null异常
public class Test{
public static void main(String[] args) {
try {
System.out.println("执行开始");
Map<String, String> map = null;
System.out.println(map.get("2121"));
}catch(NullPointerException e) { //为null报错
System.err.println("为null报错");
e.printStackTrace();
}finally {
System.out.println("执行完毕");
}
}
}
try块里面触发的异常类型要对应catch(异常类型 e),不然是不会处理异常的
执行结果:
执行开始
为null报错
java.lang.NullPointerException //e.printStackTrace();
at amazon.Test.main(Test.java:10)
执行完毕
也就是说,你使用try…catch…finally来处理异常又方便又可以让代码执行到最后。
多个异常处理
同上
多加几个catch块就行了
例子:
public class Test{
public static void main(String[] args) {
try {
System.out.println("执行开始");
Map<String, String> map = null;
System.out.println(map.get("2121"));
}catch(NullPointerException e) { //为null报错
System.err.println("为null报错");
e.printStackTrace();
}catch(Exception e){
System.err.println("未知报错");
e.printStackTrace();
}finally {
System.out.println("执行完毕");
}
}
}
如果你不知道会报什么异常,就用Excption,这是所有异常的父类,所有异常都可以跑出异常。
throws关键字
throws关键字是用在方法上,用来告诉调用者本方法可能出现的异常,不做异常处理,交给调用方法的上层处理。
语法:修饰符 返回值类型 方法名()throws 异常类型,异常类型{ }
例子:
public class Test{
public static void main(String[] args) {
try {
System.out.println(show(19));
}catch(Exception e){
System.err.println("未知报错");
e.printStackTrace();
}
}
public static int show(int x)throws Exception{
return x/0;
}
}
输出结果:
未知报错
java.lang.ArithmeticException: / by zero
at amazon.Test.show(Test.java:16)
at amazon.Test.main(Test.java:7)
throws关键字是不做异常处理,只把异常抛出给上一层,上层怎么处理这个异常都和throw是没关系了。
throw关键字
throw关键字是写在方法块里面的,由人为自定义抛出异常,。
例子:
public class Test{
public static void main(String[] args) {
try {
throw new Exception("未知错误");
}catch(Exception e){
e.printStackTrace();
}
}
}
输出结果:
java.lang.Exception: 未知错误
at amazon.Test.main(Test.java:7)
异常处理模型
上面已经把异常处理的的方式都说明了,throw、throws、try…catch…finally。
接下来我们结合一起使用
当使用throws关键字处理异常的时候,方法里面不用写catch块因为throws是往上抛出异常的
public class Test{
public static void main(String[] args) {
try {
show();
} catch (Exception e) {
// TODO: handle exception
System.err.println("报错");
e.printStackTrace();
}
}
public static void show() throws Exception{
try {
System.out.println("执行开始");
System.out.println( 10/0);
}finally{
System.out.println("执行结束");
}
}
}
执行结果
执行开始
执行结束
报错
java.lang.ArithmeticException: / by zero
at amazon.Test.show(Test.java:19)
at amazon.Test.main(Test.java:7)
使用throw关键字在同方法内,要使用用try…catch块,因为throw是手动抛出异常在说明位置都由自己控制
public class Test{
public static void main(String[] args) {
try {
throw new Exception("报错");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
执行结果
java.lang.Exception: 报错
at amazon.Test.main(Test.java:7)
RuntimeException
RuntimeException(运行时异常),是不受检查的,就是你在编译的时候是不会给你提示某个地方会报错,只有在运行的时候出现。运行时异常不需要try…catch…或throws 机制去处理的异常,如果发生了该异常一定是程序员的问题。
比如经典的1/0,空指针等这些都会在程序运行的时候报错。
自定义异常类
继承Exception或RuntimeException就可以自定义异常类了
//测试类
public class Test{
public static void main(String[] args) {
try{
throw new MyExcetion("10不能处于0");
}catch(MyExcetion e){
e.printStackTrace();
}
}
}
//自定义异常类 也可以继承RunTimeException
class MyExcetion extends Exception{
//创建无参构造
public MyExcetion(){}
//创建有参构造
public MyExcetion(String message){
super(message); // 把参数传递给Throwable的带String参数的构造方法
}
}
Assert断言
简介
断言相当于是一个if判断条件,为true的时候正常运行,为false的时候中断运行然后抛出报错。
断言可以随时开启和关闭
断言不具备继承性,也就是说父类禁止断言子类也可以开启断言。
判断
//测试类
public class Test{
public static void main(String[] args) {
boolean bool = false;
assert bool = true;
System.out.println(bool); //如果打开了断言则会为true
}
}
开打关闭断言
- 选择菜单:run --> run Configurations
- 打开断言:-ea
- 关闭断言:-da,或者删除-ea
使用方法
例子1:
public class CeShiText {
public static void main(String[] args) {
assert(1>2);
System.out.println("执行完成");
}
}
和抛出异常差不多,断言为false就会抛出报错AssertionError
执行结果
Exception in thread "main" java.lang.AssertionError
at amazon.CeShiText.main(CeShiText.java:7)
例子2:
public class CeShiText {
public static void main(String[] args) {
boolean boo = false;
try {
assert boo :"执行错误";
System.out.println("执行成功");
} catch (AssertionError e) {
System.out.println(e.getMessage());
}
}
}
执行结果
执行错误
这种方式是如果为true则忽略冒号后面的直接往下执行,如果为false则抛出AssertError异常,而内容则是冒号后面的。
设置断言的使用范围
-ea java -ea 打开所有用户类的assertion
-da java -da 关闭所有用户类的assertion
-ea: java -ea:MyClass1 打开MyClass1的assertion
-da: java -da: MyClass1 关闭MyClass1的assertion
-ea: java -ea:pkg1 打开pkg1包的assertion
-da: java -da:pkg1 关闭pkg1包的assertion
-ea:… java -ea:… 打开缺省包(无名包)的assertion
-da:… java -da:… 关闭缺省包(无名包)的assertion
-ea:… java -ea:pkg1… 打开pkg1包和其子包的assertion
-da:… java -da:pkg1… 关闭pkg1包和其子包的assertion
-esa java -esa 打开系统类的assertion
-dsa java -dsa 关闭系统类的assertion