关注「Java视界」公众号,获取更多技术干货

异常(实际项目中的异常处理)

 

一、什么是异常

异常指的是导致程序中断执行的一种指令流。

如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。 
如果不想终止,则必须捕获所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。

若程序中有一处错,程序在中途运行停止,如下:

public class Test {
    public static void main(String[] args) {
        System.out.println("1111111111");
        System.out.println("2222222"+ (9/0));
        System.out.println("3333333333");
    }
}
1111111111
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Exception.Test.main(Test.java:9)

可以看出程序未按正常流程执行,而是中断了,这个就是运行时异常,导致程序不能顺利执行完毕。

 

二、异常处理机制

若这个导致的中断语句是非核心语句,我们不想让这个非核心语句影响整个程序的运行,而继续向下执行,就需要一个异常处理机制了。异常处理机制由try、catch、finally三个关键字来完成,基本语法格式如下:

try {
        // 可能出现异常的语句
} catch (异常类型 异常对象){
        // 异常处理语句
} catch (异常类型 异常对象){
        // 异常处理语句
} finally {
    // 不管是否有异常都要执行的语句
}

例如上面的代码,第二句可能会有异常,就这第二句处加上try即可,如下:

public class Test {
    public static void main(String[] args) {
        System.out.println("1111111111");
        try {
            System.out.println("2222222"+ (9/0));
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        System.out.println("3333333333");
    }
}

结果:

1111111111
java.lang.ArithmeticException: / by zero
	at Exception.Test.main(Test.java:10)
3333333333

可以看出,第二个打印虽然还是有异常,但是因为提前进行了异常处理,不影响后面代码的执行,第三个打印正常执行了。

这里注意finally里面的语句不管异常是否出现都会被执行。

 

三、异常处理流程

 

(1)在程序运行的过程中才会产生异常,而一旦程序执行中产生了异常之后将自动实例化指定异常类;

(2)对于没有手写异常处理的,则会采用JVM默认异常处理方式,首先进行异常信息打印,然后直接退出当前程序;

(3)若存在异常处理,那么这个产生异常类的实例化对象会被try捕获,然后与catch里的异常类进行匹配对比,若匹配则用这个catch中的处理语句进行处理,若不匹配则继续匹配下一个catch;

(4)不管是否处理,finally语句始终会被执行。

 

四、Error和Exception的区别

Error:是程序未执行时出现的错误,开发者无法处理;

Exception:程序执行时出现的异常,开发者可以处理,实际开发中只需要关注异常即可;

 

五、异常继承关系

Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类(Throwable是一个类)。Throwable又派生出Error类和Exception类。

异常除了RuntimeException运行时异常(非检测异常),还有非运行时异常(或者叫检测异常、编译时异常)。 

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。 

六、多个异常处理范围问题

类型范围大的异常应该放在最后一个catch中,若放在前面的catch中则后面的catch将不在匹配执行。

 

七、throws关键字

在程序运行时可能会产生异常,如果想明确告诉他人是何种异常可以使用throws关键字在方法上声明。

class DiveMethod{
    public static double div(int x, int y) throws ArithmeticException{
        return x/y;
    }
}

public class ThrowsTest {
    public static void main(String[] args) {
        try {
            System.out.println(DiveMethod.div(100, 6));
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
}

上面的DiveMethod的div()方法就用throws声明了可能产生的异常,且该异常在调用处处理,即谁调用谁处理(也可以不处理,继续向上抛出)。若继续抛出则如下:

class DiveMethod{
    public static double div(int x, int y) throws ArithmeticException{
        return x/y;
    }
}

public class ThrowsTest {
    public static void main(String[] args) throws ArithmeticException {
        System.out.println(DiveMethod.div(100, 6));
    }
}

 

八、throw关键字

 

throws是在方法处声明该方法可能出现的异常类型,throw则主要表示手动进行异常的抛出。

public class ThrowsTest {
    public static void main(String[] args) throws ArithmeticException {
        try {
            throw new Exception("手动抛出异常对象");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

九、throws和throw的区别

  • throws:在方法定义上使用,表示此方法中可能出现的异常,并且告诉调用者要处理该异常;
  • throw:在代码块上使用,手动进行异常对象的抛出。

 

十、RuntimeException和Exception的区别

  • RuntimeException是Exception的子类;
  • RuntimeException标识的异常可以不强制处理,Exception标识的异常必须强制性处理。

 

十一、自定义异常类

JDK定义的异常类不够使用时,就需要自定义异常类。实现方式为继承Exception或者RuntimeException。

// 自定义异常类
class SelfExceptionDemo extends Exception {
    public SelfExceptionDemo(String msg){
        super(msg);
    }
}

class Div {
    public static double divTest(int x, int y) throws SelfExceptionDemo {
        return x/y;
    }
}

public class SelfException{
    public static void main(String[] args) {
        try {
            Div.divTest(10,4);
        } catch (SelfExceptionDemo selfExceptionDemo) {
            selfExceptionDemo.printStackTrace();
        }
    }
}

 

十二、实际项目中的异常处理

异常处理再实际项目中,很重要,特别是在和前端交互的时候,如果后台出现错误,前端看见的是一堆对他们来说很难理解的500错误,可能会干起来。如果能给予一些错误提示就会利于沟通。

 

补充一:方法重写时,子类声明异常能否超过父类的范围?

在java中,当子类要重写父类中的方法,那么子类重写这个方法时候,所要声明的异常不应该比父类的大。只能是小等,或者可以没有。

 

 

 

posted @ 2022-06-25 14:03  沙滩de流沙  阅读(181)  评论(0编辑  收藏  举报

关注「Java视界」公众号,获取更多技术干货