今天意外在崩溃上报平台发现一个异常为UndeclaredThrowableException,看名字就比较好奇,大家可以搜索下,尝试回答:
- 什么时候会抛出此异常?
- 为什么[1]中重新封装为此异常抛出,这么设计的原因是?
更多问答 >>
-
每日一问 | android hidden api 不是禁用反射,以及如何突破,「元反射」不行了?
2022-02-08 23:51 -
每日一问 | 如何构造一个 hide interface 的实现类?
2022-02-08 23:51 -
每日一问 | 脱糖对于Android 打包期间插桩的有什么影响?
2022-03-07 21:26 -
每日一问 .class vs Class.forName() vs loadClass() 类加载傻傻分不清楚?
2022-02-11 14:22 -
每日一问 | 被声明为private final 的内部类,能生成一个子类对象吗?逆天篡改~
2022-04-15 21:13 -
每日一问 | Gson中序列化对象的操作有低侵入的优化方案吗?
2021-12-02 00:50 -
每日一问 | 好奇ActivityThread中为什么会有一个 Application的集合?
2021-08-30 21:36 -
每日一问 | 关于 Activity 重建,值得探究的几个问题
2021-08-30 21:37 -
每日一问 | ViewModel 在什么情况下的「销毁重建」能够对数据进行无缝恢复?
2021-08-25 18:11
百度了一下,这篇文章 说是在动态代理类里面抛出的异常。
反编译自动生成的代理类会看到这样的代码:
熟悉动态代理原理的同学会知道,这个自动生成的代理类会实现目标接口,并在所有重写的方法里面去调用我们实现的InvocationHandler的
比如上面这段代码(里面的invoke
方法。super.h
就是InvocationHandler的实例),虽然有对异常作try catch处理,但它只catch了RuntimeException和Error,这就说明,只要我们实现的InvocationHandler重写的invoke
方法抛出的异常不是RuntimeException或Error的子类,就会报UndeclaredThrowableException了,比如常见的InvocationTargetException、RemoteException、IOException等等,这些都不是属于RuntimeException,照推荐的做法,是应该第一时间catch住的。但由于我们在重写InvocationHandler的invoke
方法的时候,IDE自动生成的代码:是带上了throws Throwable的,这就导致原来该try的Checked Exception没有了提示!从而忽略了加try catch这一步,让这些Checked Exception往外逃了!
自动生成的代理类catch到Throwable之后,为什么还要套一个UndeclaredThrowableException再往外抛出呢?
那篇文章里说是java继承原则的原因,我觉得不是,我觉得应该是代码规范问题,是出于程序的健壮性考虑。接着上面那句话,在java中,对于这些Checked Exception处理方法只有两种:要么在方法里加throws XXX往外抛出,要么显式catch住,如果是往外抛出的话,最后程序会发生什么就由不得你了,比如这次的动态代理类,它的做法就是套一个你不认识的异常继续往外抛。有个说法是,不要把Checked Exception当异常,要把它当成某个操作的else分支,比如网络请求经常会发生的ConnectException和SocketTimeoutException,还有读写文件时的FileNotFoundException,这些都是不可避免的,发生这些异常,很多时候并不是代码逻辑有问题,而是一些外部的不可控因素造成的。对于这种情况,如果我们把【正常的代码逻辑】和【Checked Exception】看成是一个整体的if else的流程,就像这样:这样不就很自然了?
1.动态代理时处理检查异常失败了
2.动态代理时反射处理返回值为人工转换,说白了就是可以瞎写而不被语言规范所限制,设计出来这个异常是为了告诉开发者,已经最大程度告诉你是什么地方存在问题,你要为出现的问题负责