java 异常

异常(我们想让程序遇到问题时还能继续执行/)

程序在运行过程中,由于意外情况导致程序发生异常事件,默认情况下发生的异常会中断程序运行。
在Java中,把常见的异常情况,都抽象成了对应的异常类型,那么每种异常类型都代表了一种特定的异常情况。
当程序中出现一种异常情况时,也会创建并抛出一个异常类型对象,这个对象就表示当前程序所出现的问题。

异常体系中的根类是: java.lang.Throwable ,该类下面有俩个子类型, java.lang.Error 和 java.lang.Exception

Error ,表示错误情况,一般是程序中出现了比较严重的问题,并且程序自身并无法进行处理。
Exception ,表示异常情况,程序中出了这种异常,大多是可以通过特定的方式进行处理和纠正的,并且处理完了之后,程序还可以继续往下正常运行。

异常种类
我们平时使用的异常类型,都是 Exception 类的子类型,它们把异常划分成了俩种:
编译时异常
运行时异常

编译时异常,继承自 Exception 类,也称为checked exception,编译器在编译期间,会主动检查这种异常,发现后会报错,并提示我们要对这种异常进行处理。

运行时异常,继承自 RuntimeException 类,也称为unchecked exception,编译器在编译期间,不会检查这种异常,也不要求我们去处理,但是在运行期间,代码中可能会抛出这种类型的异常。
在这里插入图片描述
手动抛异常(用throw 并且new一个对象)

public static double div(double i,double j) {
		if(j>0) {
			throw new NullPointerException("空指针");
		}
		return i/j;
	}

自动抛异常(jvm)

异常传播

如果一个方法中抛出了异常,并且一直没有进行处理,那么这个异常将会抛给当前方法的调用者,并一 直向上抛出,直到抛给JVM,最后JVM将这个异常信息打印输出,同时程序运行的停止。

public class Test {
    public static void main(String[] args) {
        System.out.println("hello");
        test1();
        System.out.println("world");
    }
    public static void test1(){
   	 	test2();
    }
    public static void test2(){
    	test3();
    }
    public static void test3(){
    	int a = 1/0;
    }
}


//运行结果:
hello
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.demo.Test.test3(Test.java:16)
at com.demo.Test.test2(Test.java:13)
at com.demo.Test.test1(Test.java:10)
at com.demo.Test.main(Test.java:5)

层层上抛给jvm
在这里插入图片描述
自动抛出异常
当前java代码中,出现了提前指定好的异常情况的时候,代码会自动创建异常对象,并且将该异常对象抛出。

例如,当代码中执行 int a = 1/0; 的时候,代码会自动创建并抛出 ArithmeticException 类型的异常对象,来表示当前的这种异常情况。(算术异常)

例如,当前代码中执行 String str = null; str.toString(); 的时候,代码会自动创建并抛出NullPointerException 类型的异常对象,来表示当前这种异常情况。(空指针异常)

手动抛出异常

以上描述的异常情况,都是JVM中提前规定好的,我们不需要干预,JVM内部自己就会创建并抛出异常 对象。 但是在其他的一些情况下,我们也可以手动的创建并抛出异常对象,其效果也是一样的。

异常捕获

当一个方法内,抛出了编译异常的时候,编译器在编译期间检查到,就会报错,提示我们有俩种修改方案:
把这个异常在方法上进行声明抛出(throws Exception)直接向上抛出/jvm/调用者
把这个异常再方法内进行捕获处理(try-catch)抛出之后处理

try-catch

try-catch 语句块,就是用来对指定代码,进行异常捕获处理,并且处理完成后,JVM不会停止运行,代码还可以正常的往下运行!

public class Test {
    public static void main(String[] args) {
        System.out.println("hello");
        Test t = new Test();
    try {
   	 	t.test("zs");
    } catch (Exception e) {
        //打印输出发生异常的时候,栈里面的方法调用情况,方便我们定位和修改代码
        e.printStackTrace();
    }
        System.out.println("world");
    }
    
    public void test(String name)throws Exception{
        if(!"tom".equals(name)){
        	throw new Exception("用户名不正确");
    	}
   }
}

//运行结果:
hello
world
java.lang.Exception: 用户名不正确
at com.briup.demo.Test.test(Test.java:20)
at com.briup.demo.Test.main(Test.java:9)

3 捕获多种异常
如果try语句块中的多句代码,都会抛出异常,并且是不同类型的异常,那么catch语句块就有不同的写法,来处理这几个不同类型的异常。

public static void main(String[] args) {
    String className = "com.briup.demo.Student";
    String methodName = "sayHello";
    try {
    //forName声明抛出ClassNotFoundException
    Class c = Class.forName(className);
    //getMethod方法声明抛出NoSuchMethodException
    Method m = c.getMethod(methodName);
    //invoke方法声明抛出IllegalAccessException和InvocationTargetException
    m.invoke(null);
    } catch (ClassNotFoundException | NoSuchMethodException |
    IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
    }
}

或者
    try {
    //forName声明抛出ClassNotFoundException
    Class c = Class.forName(className);
    //getMethod方法声明抛出NoSuchMethodException
    Method m = c.getMethod(methodName);
    //invoke方法声明抛出IllegalAccessException和InvocationTargetException
    m.invoke(null);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
//建议把大的异常写后面

finally语句

try-catch语句块,虽然可以捕获并处理异常情况,但是它也会改变代码的执行流程

只要使用 finally 关键,就可以保证指定代码一定会执行,无论是否发生异常

finally最后才会执行且一定会执行

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码,且无论上面是否抛出异常还是继续执行,这段代码都会执行且最后执行
}

自定义异常

异常都是Throwable的子类/Error/Exception(runtime/运行时异常,uncheck异常 exception,编译时异常,check异常)

比如自定义ModifyUserInfoExceptin异常

public class ModifyUserInfoExceptin extends RuntimeException{
    public ModifyUserInfoExceptin(){
    }
    public ModifyUserInfoExceptin(String message) {
    	super(message);
    }
}

final finally 和 finalize()区别
final 用于修饰类、方法和变量。是一种非访问修饰符
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
finalize()是Object的protected方法,GC在回收对象之前会调用该方法进行垃圾回收。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值