Java異常throws和throw區別都沒搞懂,面試感覺很慌啊

程序員、Java後端、面試題、異常類型、日誌

吐槽

最近看公司業務代碼發現異常那塊天天用,但理解不深啊

趕緊複習下,我還是有一顆學習的心

互聯網項目一個異常、一個日誌都非常重要,設計的不好後果很痛苦。

Java異常throws和throw區別都沒搞懂,面試感覺很慌啊

異常類型

Throwable有兩個子類,Error和Exception

Checked Exception

Unchecked Exception

基本概念掃盲

  • 異常和錯誤的區別是,異常是可以被處理的,而錯誤是沒法處理的。
  • Error也是unchecked exception,也是無法預先處理的。
  • 所有checked exception都是需要在代碼中處理的,它們的發生是可以預測的

check異常

如Exception /IOException

uncheck異常

RuntimeException及他的子類

check異常總結

  1. 編譯保證,沒catch或throws編譯報錯
  2. throw的是check異常就當前方法必須 throws Exception 或catch 住
  3. throw的是check異常throws Exception這個異常了,上層方法必須 catch

uncheck異常總結

  • 公司的自定義異常類都是基礎RuntimeException,然後配合異常枚舉
  • com.google.common.base.Preconditions#checkArgument(boolean, java.lang.Object) 公司大佬喜歡用這個異常工具,自己可以參考造一個出來

異常理解

編譯錯誤案例代碼

public static void throwChecked(int a)
{
 if (a > 0)
 {
 //自行拋出Exception異常
 //該代碼必須處於try塊裡,或處於帶throws聲明的方法中
 throw new Exception("a的值大於0,不符合要求");
 }
}

idea 會提示 :Unhandled exception: java.lang.Exception

正常異常案例代碼

public static void throwChecked(int a)throws Exception
{
 if (a > 0)
 {
 //自行拋出Exception異常
 //該代碼必須處於try塊裡,或處於帶throws聲明的方法中
 throw new Exception("a的值大於0,不符合要求");
 }
}

企業自定義異常類

優秀IT企業裡不是創建一堆自定義異常,而是異常類配合異常枚舉來設計

一般業務系統自定義異常類不要少過3個

get/set方法我就省略了

public class WangException extends RuntimeException {
 /**錯誤碼*/
 private WangErrorCodeEnum errorCode;
 /**詳細錯誤信息*/
 private Map errorMap = new HashMap();
 /**
 * 帶參構造器.
 * @param errorCode
 */
 public WangException(WangErrorCodeEnum errorCode) {
 super(errorCode.getDesc());
 this.setErrorCode(errorCode);
 }
 /**
 * 帶參構造器
 */
 public WangException(WangErrorCodeEnum errorCode, String message) {
 super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
 this.setErrorCode(errorCode);
 }
 /**
 * 帶參構造器.
 * @param errorCode
 * @param errorContext
 */
 public WangException(WangErrorCodeEnum errorCode, ErrorContext errorContext) {
 this(errorCode, findMessage(errorContext));
 }
 /**
 * 帶參構造器.
 * @param errorCode
 * @param errorMap
 */
 public WangException(WangErrorCodeEnum errorCode, Map errorMap) {
 this(errorCode);
 this.errorMap = errorMap;
 }
 /**
 * 帶參構造器.
 * @param errorCode
 * @param message
 */
 public WangException(WangErrorCodeEnum errorCode, String message, Map errorMap) {
 super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
 this.setErrorCode(errorCode);
 this.errorMap = errorMap;
 }
 /**
 * 帶參構造器.
 *
 * @param message
 */
 public WangException(String message) {
 super(message);
 this.setErrorCode(WangErrorCodeEnum.UNKNOWN_SYS_ERROR);
 }

錯誤枚舉

public enum WangErrorCodeEnum {
 SYS_ERROR("SYS_ERROR", "系統錯誤,請重試"),
 UNKNOWN_SYS_ERROR("UNKNOWN_SYS_ERROR", "未知的系統異常"),

高級點的異常枚舉

有日誌級別、是系統還是業務異常、日誌是error還是warn、info等等

SYSTEM_ERROR("000", ErrorLevels.ERROR,
 ErrorTypes.SYSTEM, "系統異常"),

模板模式

異常從dao、service等等拋上來後,

需要把異常信息轉換封裝返回給前端、或rpc調用端等等

這裡一般可以採用模板模式,把各種異常的catch 轉換封裝

業務代碼裡只要調用模板代碼即可,什麼異常轉換、日誌記錄都統一管理,

業務代碼乾淨多了,技術經理看到又可以加工資了

日誌規範

生產上儘量把info、error、warn分清楚

切記不要都打到error裡面了(很多公司對error非常敏感的)

異常日誌打印儘量把 場景、異常具體原因、影響業務等等打清楚,

異常碼異常描述儘量精細

大型分佈式項目中日誌好不好

決定了下班早不早,

平時寫業務代碼習慣打印“其他異常”,生產出故障了就發現自己是多麼的坑爹

分佈式trace_id非常強大,後邊我研究下整理整理

這就是我知道的異常設計最優雅的案例,程序員專家可以告訴我更優雅的


分享到:


相關文章: