亚洲香蕉成人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| 久久精品久久精品亚洲人| 欧美午夜视频在线观看| 亚洲一区二区三区四区视频| 国产成人精品最新| 日韩一区二区精品视频| 国产精品都在这里| 成人av在线天堂| 欧美极品在线视频| 久久国产精品免费视频| 欧美尤物巨大精品爽| 亚洲无线码在线一区观看| 国产成人精品久久二区二区| 日韩av不卡在线| 亚洲精品91美女久久久久久久| 国产亚洲欧美aaaa| 中文字幕日韩在线观看| 亚洲天堂免费在线| 欧美高清理论片| 久热精品视频在线观看一区| 日韩中文在线中文网三级| 久久精品国亚洲| 国产精品久久久久一区二区| 色诱女教师一区二区三区| 91欧美日韩一区| 欧美亚洲国产成人精品| 久久99精品久久久久久噜噜| 亚洲三级免费看| 97免费在线视频| 国产剧情久久久久久| 欧美野外wwwxxx| 欧美亚洲成人免费| 中文国产成人精品久久一| 亚洲激情在线观看视频免费| 国产日韩欧美日韩| 亚洲丁香婷深爱综合| 成人网页在线免费观看| 久久6精品影院| 日韩欧美大尺度| 97国产在线视频| 精品亚洲国产成av人片传媒| 久久婷婷国产麻豆91天堂| 91精品国产综合久久香蕉922| 久久色免费在线视频| 中文字幕亚洲字幕| 中文字幕在线亚洲| 日韩av网址在线| 亚洲欧美日韩国产中文| 国内免费精品永久在线视频| 亚洲在线视频观看| 欧美中文字幕在线视频| 亚洲欧洲国产伦综合| 人人做人人澡人人爽欧美| 欧美猛交ⅹxxx乱大交视频| 久久人人看视频| 亚洲欧美成人一区二区在线电影| 久久影视电视剧凤归四时歌| 欧美另类老女人| 久久精品视频中文字幕| 久久69精品久久久久久久电影好| 精品视频在线播放色网色视频| 国产精品视频xxx| 欧美一级淫片丝袜脚交| 国产精品三级网站| 亚洲成av人片在线观看香蕉| 亚洲品质视频自拍网| 91精品视频大全| 深夜成人在线观看| 亚洲伊人一本大道中文字幕| 在线观看亚洲视频| 欧洲亚洲女同hd| 日韩av成人在线观看| 综合网中文字幕| 日韩少妇与小伙激情| 亚洲欧美www| 国产日本欧美一区| 欧美亚洲国产视频| 欧美国产日韩在线| 久久青草精品视频免费观看| 色悠久久久久综合先锋影音下载| 国产欧美亚洲视频| 亚洲激情久久久| 亚洲欧美制服综合另类| 久久久久久高潮国产精品视| 欧美专区在线视频| 国产精品高清网站| 国产精品video| 亚洲欧美综合精品久久成人| 8x海外华人永久免费日韩内陆视频| 这里只有精品在线播放| 6080yy精品一区二区三区| 精品国产91乱高清在线观看| 国产精品视频成人| 亚洲国产成人精品一区二区| 日韩欧美在线免费观看| 欧美一区二区三区四区在线| 精品一区二区电影| 播播国产欧美激情| 日韩av在线网址| 91精品视频在线免费观看| 欧美精品精品精品精品免费| 久久人人爽人人爽人人片亚洲| 国产精品成熟老女人| 亚洲人精品午夜在线观看| 一区二区三区精品99久久| 亚洲精品国精品久久99热一| 欧美人与物videos| 日韩在线视频播放| 日韩有码在线电影| 欧美刺激性大交免费视频| 欧美高清电影在线看| 久久久久久久一| 欧美高跟鞋交xxxxhd| 精品小视频在线| 色噜噜国产精品视频一区二区| 国产国语刺激对白av不卡| 亚洲人成在线一二| 亚洲第一二三四五区| 8x海外华人永久免费日韩内陆视频| 国产精品久久久久久五月尺| 亚洲影院色在线观看免费| 亚洲一区二区久久久久久久| 另类视频在线观看| 成人在线中文字幕| 成人精品视频在线| 久久久这里只有精品视频| 疯狂做受xxxx高潮欧美日本| 欧美日韩人人澡狠狠躁视频| 久久久精品在线| 中文字幕av一区中文字幕天堂| 日韩免费观看视频| 成人精品网站在线观看| 国产成人精品视频| 久久影视电视剧免费网站| 亚洲欧美第一页| 精品国产31久久久久久| 久久深夜福利免费观看| 欧美电影《睫毛膏》| 亚洲成人av资源网| 成人福利网站在线观看11| 久久国产加勒比精品无码| 97av视频在线| 久久精品影视伊人网| 最近更新的2019中文字幕| 国内精品久久久久伊人av| 欧美色视频日本高清在线观看| 国产精品视频一区国模私拍| 国语自产精品视频在线看一大j8| 欧美最猛黑人xxxx黑人猛叫黄| 午夜精品蜜臀一区二区三区免费| 日韩精品在线电影| 日韩av网址在线| 亚洲美腿欧美激情另类| 精品久久久久久中文字幕| 欧美性猛交xxxx免费看| 九九热这里只有精品免费看| 啊v视频在线一区二区三区| 久久全球大尺度高清视频| 亚洲视频第一页| 国产高清在线不卡| 日韩电影中文字幕|