java中如何正常处理异常
java异常简述
程序的异常:Throwable
Error:严重的问题,操作系统或者虚拟机出现的问题,我们无法处理(比如内存溢出)。
Exception:问题,需要处理。
非RunTimeException:编译期问题,必须处理,不然编译无法通过。
RunTimeException及其子类:运行期异常,代码不严谨。可以处理 也可以不处理。
异常如果我们不处理,jvm会自动帮我们处理,把异常原因,名称和位置打印在控制台。但是程序会终止。
我们自己如何处理异常:
1.try--catch--finally
try里面的代码越少越好,catch里面必须要有东西,哪怕是最简单的提示。try catch 处理后的代码块还会继 续执行。
2.throws抛出:在方法上抛出异常,代表有可能出现异常。交给程序的调用者去处理。
3.throw抛出:在方法内部抛出异常,一定会出现这个异常。
4.finally:一定会被执行的语句块,特例(执行到finally jvm停止了)常用于IO释放资源和数据库操作。
面试题1:final finally finalize 的区别。
答:final是异常处理的关键字,是try catch执行后一定执行的代码块。
final是一个修饰符:修饰类类不能被继承。 修饰方法:方法不能被重写。 修饰变量:变量为常量。
finalize:是Object的一个方法,表示垃圾回收。我们不需要处理。
面试题2:当catch里面有return的时候,还会走finally语句吗?如果会是return前还是return后。
答:会走,在return之前。
自定义异常:可以继承Exception和RunTimeException。通过构造方法调用父类构造显示异常信息。
异常注意事项:
1.子类重写父类方法:子类的方法必须抛出跟父类相同或者父类异常的子类(儿子不能比父亲更坏)。
2.如果被重写的方法没有抛出异常,那么就不能出现throws只能try catch 处理异常。
异常处理机制的应用
实际项目中结合处理异常:(当资源不存在/参数错误/内部错误...必须明确返回给前端。)
直接这样写,抛出异常,会使异常杂乱无章。把一些没有必要暴漏给客户端的堆栈等等信息给暴露出去。
所以针对异常我们需要统一错误响应格式。
如何自定义异常
我们写一个异常类,集成Exception 或者 RunTimeException:已知异常用RunTimeException,未知异常用Exception。
未知异常:是后端代码逻辑导致的异常,可以理解为bug,对前端和用户来说没有什么实际意义,只需要返回如"服务器内部错误"和500错误状态,无需返回具体的异常信息,但是可以把它打印在日志中供后端程序员进行检索。
已知异常:会料到这个地方可能会发生的异常,可以理解为一种后端一种非法的提示,可以将它同一自定义异常归类,然后返回给前端。当然 我们也可以将它传输成RestFallRespons 的结果返回给前端,但是异常处理更简单。
关于http异常的父类 具体的子类当我们用SpringBoot的全局捕获异常的时候,可以捕获定义的异常。全局捕获异常,通常会根据异常的类型定义多个异常,当我们捕获到RunTimeException的时候,就不会捕获Exception,但是Exception要保留(漏网之鱼),我们无法预料到所有会发生的异常,所以是有必要的。它会拦截我们没有定义出来的未知异常。
如图一个捕获异常的案例,捕获exception,我们可以通过@ResponseStatus注解给他设置http状态code。
统一的异常返回结果 springBoot全局捕获异常 测试异常的rest接口 测试捕获Exception异常如图:postman测试结果,全局异常返回的结果是我们定义好的UnifyResponse。
构建的一个自定义返回异常上图中我定义了一个自定义异常,可是错误码和错误提示的message信息是用硬编码实现的,很显然这中方法是不规范的,不符合开闭原则也不适应国际化。一般来说更好的做法我们可以将所有的异常信息通过配置文件来实现。这样我们只需传入code 就可以实现异常返回消息的查找。
如下图:我们定义了一个配置文件exception-dode.properties和ExceptionCodeConfiguration配置解析类。
仔细对应两者之间的参数即可对应。若要想被spring容器加载需要加上@Component注解。当然别忘了加上get和set方法。
配置注解是:@ConfigurationProperties
再加上路径注解:@@PropertySource(value = "classpath:config/exception-code.properties" )
配置文件 配置文件对应的组件类这样我们在调用过程中只需将这个类通过@Autowired属性注入,即可使用。
配置文件类注入使用自定义异常思考
我们通过定义一个HttpException异常类来处理Http相关的异常,但是我们不能每一个状态去定义一个异常和一个全局捕获异常的方法吧。所以我们可以定义多个状态类去继承HttpExceptionb并且初始化http状态码code,只去捕获HttpException即可。
NotFoundException继承自HttpException