亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Java如何自定義異常打印非堆棧信息詳解

2024-07-14 08:40:19
字體:
來源:轉載
供稿:網友

前言

在學習Java的過程中,想必大家都一定學習過異常這個篇章,異常的基本特性和使用這里就不再多講了。什么是異常?我不知道大家都是怎么去理解的,我的理解很簡單,那就是不正常的情況,比如我現在是個男的,但是我卻有著女人所獨有的東西,在我看來這尼瑪肯定是種異常,簡直不能忍。想必大家都能夠理解看懂,并正確使用。

但是,光學會基本異常處理和使用不夠的,在工作中出現異常并不可怕,有時候是需要使用異常來驅動業務的處理,例如: 在使用唯一約束的數據庫的時候,如果插入一條重復的數據,那么可以通過捕獲唯一約束異常DuplicateKeyException來進行處理,這個時候,在server層中就可以向調用層拋出對應的狀態,上層根據對應的狀態再進行處理,所以有時候異常對業務來說,是一個驅動方式。

有的捕獲異常之后會將異常進行輸出,不知道細心的同學有沒有注意到一點,輸出的異常是什么東西呢?

下面來看一個常見的異常:

java;">java.lang.ArithmeticException: / by zero at greenhouse.ExceptionTest.testException(ExceptionTest.java:16) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

一個空指針異常:

java.lang.NullPointerException at greenhouse.ExceptionTest.testException(ExceptionTest.java:16) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

大家有沒有發現一個特點,就是異常的輸出是中能夠精確的輸出異常出現的地點,還有后面一大堆的執行過程類調用,也都打印出來了,這些信息從哪兒來呢? 這些信息是從棧中獲取的,在打印異常日志的時候,會從棧中去獲取這些調用信息。能夠精確的定位異常出現的異常當然是好,但是我們有時候考慮到程序的性能,以及一些需求時,我們有時候并不需要完全的打印這些信息,并且去方法調用棧中獲取相應的信息,是有性能消耗的,對于一些性能要求高的程序,我們完全可以在這一個方面為程序性能做一個提升。

所以如何避免輸出這些堆棧信息呢? 那么自定義異常就可以解決這個問題:

首先,自動異常需要繼承RuntimeException, 然后,再通過是重寫fillInStackTrace, toString 方法, 例如,下面我定義一個AppException異常:

package com.green.monitor.common.exception;import java.text.MessageFormat;/** * 自定義異常類 */public class AppException extends RuntimeException { private boolean isSuccess = false; private String key; private String info; public AppException(String key) { super(key); this.key = key; this.info = key; } public AppException(String key, String message) { super(MessageFormat.format("{0}[{1}]", key, message)); this.key = key; this.info = message; } public AppException(String message, String key, String info) { super(message); this.key = key; this.info = info; } public boolean isSuccess() { return isSuccess; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public Throwable fillInStackTrace() { return this; } @Override public String toString() { return MessageFormat.format("{0}[{1}]",this.key,this.info); }}

那么為什么要重寫fillInStackTrace, 和 toString 方法呢? 我們首先來看源碼是怎么一回事.

public class RuntimeException extends Exception { static final long serialVersionUID = -7034897190745766939L; /** Constructs a new runtime exception with <code>null</code> as its * detail message. The cause is not initialized, and may subsequently be * initialized by a call to {@link #initCause}. */ public RuntimeException() { super(); } /** Constructs a new runtime exception with the specified detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. * * @param message the detail message. The detail message is saved for  *  later retrieval by the {@link #getMessage()} method. */ public RuntimeException(String message) { super(message); } /** * Constructs a new runtime exception with the specified detail message and * cause. <p>Note that the detail message associated with * <code>cause</code> is <i>not</i> automatically incorporated in * this runtime exception's detail message. * * @param message the detail message (which is saved for later retrieval *  by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the *  {@link #getCause()} method). (A <tt>null</tt> value is *  permitted, and indicates that the cause is nonexistent or *  unknown.) * @since 1.4 */ public RuntimeException(String message, Throwable cause) { super(message, cause); } /** Constructs a new runtime exception with the specified cause and a * detail message of <tt>(cause==null ? null : cause.toString())</tt> * (which typically contains the class and detail message of * <tt>cause</tt>). This constructor is useful for runtime exceptions * that are little more than wrappers for other throwables. * * @param cause the cause (which is saved for later retrieval by the *  {@link #getCause()} method). (A <tt>null</tt> value is *  permitted, and indicates that the cause is nonexistent or *  unknown.) * @since 1.4 */ public RuntimeException(Throwable cause) { super(cause); } }

RuntimeException是繼承Exception,但是它里面去只是調用了父類的方法,本身是沒有做什么其余的操作。那么繼續看Exception里面是怎么回事呢?

public class Exception extends Throwable { static final long serialVersionUID = -3387516993124229948L; /** * Constructs a new exception with <code>null</code> as its detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. */ public Exception() { super(); } /** * Constructs a new exception with the specified detail message. The * cause is not initialized, and may subsequently be initialized by * a call to {@link #initCause}. * * @param message the detail message. The detail message is saved for  *  later retrieval by the {@link #getMessage()} method. */ public Exception(String message) { super(message); } /** * Constructs a new exception with the specified detail message and * cause. <p>Note that the detail message associated with * <code>cause</code> is <i>not</i> automatically incorporated in * this exception's detail message. * * @param message the detail message (which is saved for later retrieval *  by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the *  {@link #getCause()} method). (A <tt>null</tt> value is *  permitted, and indicates that the cause is nonexistent or *  unknown.) * @since 1.4 */ public Exception(String message, Throwable cause) { super(message, cause); } /** * Constructs a new exception with the specified cause and a detail * message of <tt>(cause==null ? null : cause.toString())</tt> (which * typically contains the class and detail message of <tt>cause</tt>). * This constructor is useful for exceptions that are little more than * wrappers for other throwables (for example, {@link * java.security.PrivilegedActionException}). * * @param cause the cause (which is saved for later retrieval by the *  {@link #getCause()} method). (A <tt>null</tt> value is *  permitted, and indicates that the cause is nonexistent or *  unknown.) * @since 1.4 */ public Exception(Throwable cause) { super(cause); }}

從源碼中可以看到, Exception里面也是直接調用了父類的方法,和RuntimeException一樣,自己其實并沒有做什么。 那么直接來看Throwable里面是怎么一回事:

public class Throwable implements Serializable { public Throwable(String message) { fillInStackTrace(); detailMessage = message; }  /** * Fills in the execution stack trace. This method records within this * <code>Throwable</code> object information about the current state of * the stack frames for the current thread. * * @return a reference to this <code>Throwable</code> instance. * @see java.lang.Throwable#printStackTrace() */ public synchronized native Throwable fillInStackTrace();  /** * Provides programmatic access to the stack trace information printed by * {@link #printStackTrace()}. Returns an array of stack trace elements, * each representing one stack frame. The zeroth element of the array * (assuming the array's length is non-zero) represents the top of the * stack, which is the last method invocation in the sequence. Typically, * this is the point at which this throwable was created and thrown. * The last element of the array (assuming the array's length is non-zero) * represents the bottom of the stack, which is the first method invocation * in the sequence. * * <p>Some virtual machines may, under some circumstances, omit one * or more stack frames from the stack trace. In the extreme case, * a virtual machine that has no stack trace information concerning * this throwable is permitted to return a zero-length array from this * method. Generally speaking, the array returned by this method will * contain one element for every frame that would be printed by * <tt>printStackTrace</tt>. * * @return an array of stack trace elements representing the stack trace *  pertaining to this throwable. * @since 1.4 */ public StackTraceElement[] getStackTrace() { return (StackTraceElement[]) getOurStackTrace().clone(); } private synchronized StackTraceElement[] getOurStackTrace() { // Initialize stack trace if this is the first call to this method if (stackTrace == null) {  int depth = getStackTraceDepth();  stackTrace = new StackTraceElement[depth];  for (int i=0; i < depth; i++)  stackTrace[i] = getStackTraceElement(i); } return stackTrace; }  /** * Returns the number of elements in the stack trace (or 0 if the stack * trace is unavailable). * * package-protection for use by SharedSecrets. */ native int getStackTraceDepth(); /** * Returns the specified element of the stack trace. * * package-protection for use by SharedSecrets. * * @param index index of the element to return. * @throws IndexOutOfBoundsException if <tt>index < 0 || *  index >= getStackTraceDepth() </tt> */ native StackTraceElement getStackTraceElement(int index);  /** * Returns a short description of this throwable. * The result is the concatenation of: * <ul> * <li> the {@linkplain Class#getName() name} of the class of this object * <li> ": " (a colon and a space) * <li> the result of invoking this object's {@link #getLocalizedMessage} * method * </ul> * If <tt>getLocalizedMessage</tt> returns <tt>null</tt>, then just * the class name is returned. * * @return a string representation of this throwable. */ public String toString() { String s = getClass().getName(); String message = getLocalizedMessage(); return (message != null) ? (s + ": " + message) : s; }

從源碼中可以看到,到Throwable就幾乎到頭了, 在fillInStackTrace() 方法是一個native方法,這方法也就是會調用底層的C語言,返回一個Throwable對象, toString 方法,返回的是throwable的簡短描述信息, 并且在getStackTrace 方法和 getOurStackTrace 中調用的都是native方法getStackTraceElement, 而這個方法是返回指定的棧元素信息,所以這個過程肯定是消耗性能的,那么我們自定義異常中的重寫toString方法和fillInStackTrace方法就可以不從棧中去獲取異常信息,直接輸出,這樣對系統和程序來說,相對就沒有那么”重”, 是一個優化性能的非常好的辦法。那么如果出現自定義異常那么是什么樣的呢?請看下面吧:

@Test public void testException(){ try { String str =null; System.out.println(str.charAt(0)); }catch (Exception e){ throw new AppException("000001","空指針異常"); } }

那么在異常異常的時候,系統將會打印我們自定義的異常信息:

000001[空指針異常]Process finished with exit code -1

所以特別簡潔,優化了系統程序性能,讓程序不這么“重”, 所以對于性能要求特別要求的系統。趕緊自己的自定義異常吧!

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内精品久久久久伊人av| 国产999精品久久久影片官网| 欧美精品第一页在线播放| 欧美黑人xxxx| 久久福利网址导航| 国产精品久久久久久久一区探花| 欧美精品videossex性护士| 亚洲最大福利网| 久久久国产视频91| 91精品久久久久久久久久入口| 亚洲japanese制服美女| 日韩av最新在线观看| 国产精品成人免费电影| 亚州成人av在线| 精品magnet| 久久天堂电影网| 亚洲福利精品在线| 亚洲精品福利免费在线观看| 久久免费视频在线观看| 色综合影院在线| 2019中文字幕在线观看| 亚洲综合色av| 国产精品av免费在线观看| 日韩欧美国产成人| 久久精品国产一区二区三区| 亚洲免费精彩视频| 国产精品一二三在线| 欧美成人亚洲成人日韩成人| 亚洲欧洲日产国码av系列天堂| 91在线看www| 最近中文字幕mv在线一区二区三区四区| 日韩成人免费视频| 午夜精品一区二区三区在线视频| 精品国产1区2区| 久久韩剧网电视剧| 国产精品人成电影在线观看| 综合国产在线视频| 欧美成年人视频网站| 中文字幕亚洲一区二区三区| 久久久久北条麻妃免费看| 欧美成人精品影院| 亚洲精品天天看| 精品亚洲夜色av98在线观看| 一区二区欧美日韩视频| 欧美一级免费看| 日韩视频在线免费观看| 欧美另类第一页| 日韩在线一区二区三区免费视频| 伦理中文字幕亚洲| 成人精品aaaa网站| 久久五月情影视| 日韩最新av在线| 色妞久久福利网| 中文字幕亚洲欧美| 国产视频精品xxxx| 国产乱肥老妇国产一区二| 伊人久久免费视频| 国产亚洲激情在线| 欧美色xxxx| 国产精品自产拍在线观| 久久精品夜夜夜夜夜久久| 国产精品视频男人的天堂| 久久99久久久久久久噜噜| 91在线精品播放| 免费97视频在线精品国自产拍| 国产suv精品一区二区| 亚洲欧美日韩第一区| 日韩高清电影免费观看完整版| 亚洲欧美精品一区二区| 中文亚洲视频在线| 欧美日韩亚洲精品一区二区三区| 一本大道香蕉久在线播放29| 一区二区亚洲欧洲国产日韩| 69av在线视频| 成人在线视频福利| 日韩在线观看免费网站| x99av成人免费| 日韩美女视频免费在线观看| 搡老女人一区二区三区视频tv| 亚洲乱码国产乱码精品精天堂| 亚洲欧美日韩中文在线| 久久男人的天堂| 日本精品视频在线播放| 国产欧美日韩中文字幕| 久久精品这里热有精品| 在线亚洲国产精品网| 日韩专区中文字幕| 国产精品视频久久| 国产精自产拍久久久久久| 亚洲xxxx视频| 国产精品综合不卡av| 亚洲欧洲视频在线| 久久综合免费视频影院| 亚洲福利视频久久| 黑丝美女久久久| 91精品国产自产在线观看永久| 国产日本欧美一区二区三区| 久久久av一区| 中文字幕无线精品亚洲乱码一区| 欧美激情亚洲精品| 亚洲综合精品伊人久久| 伊人亚洲福利一区二区三区| 久久婷婷国产麻豆91天堂| 中文字幕少妇一区二区三区| 久久理论片午夜琪琪电影网| 久久91精品国产91久久跳| 96sao精品视频在线观看| 亚洲精品影视在线观看| 亚洲精品www久久久| 国产精品中文字幕在线| 91人人爽人人爽人人精88v| 日韩精品在线免费观看视频| 在线视频日本亚洲性| 精品久久久久久亚洲国产300| 亚洲香蕉伊综合在人在线视看| 欧美激情手机在线视频| 亚洲一区二区三区xxx视频| 伊人久久五月天| 欧美精品18videos性欧美| 中国china体内裑精亚洲片| 91精品国产91久久久久久不卡| 日韩网站免费观看高清| 欧美日韩中文字幕在线| 欧美亚洲另类激情另类| 日韩在线观看网址| 国产欧美精品va在线观看| 91精品国产综合久久久久久久久| 亚洲在线第一页| 亚洲专区国产精品| 国产日韩亚洲欧美| 国产亚洲美女精品久久久| 国产精品电影观看| 欧美成人全部免费| 欧美另类高清videos| 国产日本欧美视频| 国产91色在线|免| 成人黄色av网站| 日韩免费黄色av| 97在线看福利| 久久人人爽人人爽爽久久| 欧美黄色www| 亚洲欧美日韩爽爽影院| 亚洲最大的av网站| 在线精品高清中文字幕| 国产精品久久久久久亚洲影视| 国产日韩亚洲欧美| 8090理伦午夜在线电影| 国产在线观看不卡| 国语自产偷拍精品视频偷| 久久国产精品电影| 欧美精品久久久久a| 国产精品国产自产拍高清av水多| 国产欧亚日韩视频| 欧美日韩国产综合视频在线观看中文| 久色乳综合思思在线视频| 在线色欧美三级视频| 91久久国产婷婷一区二区| 日韩av手机在线| 中文字幕亚洲无线码在线一区| 九九综合九九综合| 国产91在线播放| 国产精品嫩草影院久久久| 久久精品人人做人人爽| 久久免费视频这里只有精品|