异常-throw的时候,有必要new 异常对象吗?

703 阅读4分钟

throw的时候,有必要new 异常对象吗?

何时throw?一般都是在catch里。


throw的时候,有必要new异常对象吗?

一般情况下,没有必要,直接throw catch(原始异常)里的原始异常即可。

即catch到的是什么异常,就抛出什么异常。

而不是再次new 一个异常——除非确实要把catch(异常)转换为其他异常,比如要转换为新的自定义状态和自定义描述信息。

如果new异常对象,缺点是
1.多new了一次对象
2.而且,catch(原始异常)里的原始异常的自定义字段的值都丢失了

catch(BizException e){
  log.error("xxx");
  throw new BizException(e); //应该直接throw e即可,而不是throw new BizException(e)
}

为什么,catch(原始异常)里的原始异常的自定义字段的值都丢失了?

因为new 异常对象的时候,只会把jdk异常类自带的描述信息字段复制过去,其他的自定义字段(包括自定义状态和自定义描述信息)都会丢失。

image.png new异常对象的时候,只有jdk异常类自带的描述信息字段,才会被复制。 而且,如果自定义异常类重写了toString()方法,那么异常描述信息的值为原始异常类的toString()方法返回的值。

//自定义异常类
public class BizException extends RuntimeException {

protected String _errorCode = "9900"; //状态。(注:描述信息字段,直接用jdk异常类自带的描述信息字段)

  protected String _moduleCode = "";
  protected String _moduleName = "";
  protected String _subsystem = "";
  
  protected Throwable _exception; //异常

  public BizException(Throwable cause) {
    super(cause);
    this.setModule();
  }
  
public String toString() {
  String desc = this.getFullMessage();
  if (this._exception != null) {
    desc = desc + ",底层异常为:" + this._exception;
  }

  return desc;
}

public String getFullMessage() {
  String info;
  if (this._moduleCode != null && !this._moduleCode.isEmpty()) {
    info = "模块{" + this._subsystem + ":" + this._moduleCode + "},错误代码{" + this._errorCode + "},错误描述{" + this.getMessage() + "}";
  } else {
    info = "模块{" + this._subsystem + "},错误代码{" + this._errorCode + "},错误描述{" + this.getMessage() + "}";
  }

  return info;
}


强制类型转换

子类强制转换为父类,没有问题。

父类强制转换为子类,可能会有问题。解决方法?必须校验父类的实例对象是否是子类的实例对象,即通过instanceof关键字校验。如果是,才可以强制转换;如果否,强制转换就有问题。

总结 :
1> instanceof 的作用是 测试它左边的对修 是否 是它右边的类的实例。
2> 在编写Java程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法,即使他实际所引用的对象确实包含该方法。如果需要让这个引用变量来调用它运行时类型的方法,必须使用强制类型转换把他转换成运行时类型。然而,在强制转换的过程中,是有可能出现类型强制转换异常(ClassCastException),规避他的方法也很简单,利用instanceof关键字来判断是否是本类对象,如果成立的化,再进行强制类型转换。
————————————————
版权声明:本文为CSDN博主「YFL_iOS」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_18505715/article/details/72631576

异常类的强制类型转换,也遵守上面的规则。


强制转换的作用是啥?

一般就是为了访问强制转换之后类型(即子类)的数据和方法。 如果不转换,父类就访问不了子类的数据和方法。

总结

异常从哪里来?

1.外部渠道异常
跨公司,就不会直接抛出异常,而是封装为结果对象(包含状态和描述信息等字段)。

2.公司渠道异常
跨部门,最好也不要直接抛出一次,也是应该封装为结果对象(包含状态和描述信息等字段)。

3.扫码异常
1)交易项目
2)前置项目
3)网关项目
部门内部的不同项目,可以直接抛出异常。


跨项目抛出异常的时候,
1.最好不要new 异常对象,因为会丢失自定义异常的自定义字段的值。
2.除非确实要转换为另外一个自定义异常类,那么也应该带上新的自定义状态和自定义字段。

即始终要带上异常的状态和描述信息,因为处理结果的时候,需要根据状态来区分,然后不同的状态,做不同的处理,或提示不同的信息(有可能需要转换原始描述信息为新的自定义业务描述信息)。