一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 解析Java中所有錯誤和異常的父類java.lang.Throwable

解析Java中所有錯誤和異常的父類java.lang.Throwable

2020-04-09 15:11Riddick JAVA教程

這篇文章主要介紹了Java中所有錯誤和異常的父類java.lang.Throwable,文章中簡單地分析了其源碼,說明在代碼注釋中,需要的朋友可以參考下

在java語言中,錯誤類的基類是java.lang.Error,異常類的基類是java.lang.Exception。
1)相同點:java.lang.Error和java.lang.Exception都是java.lang.Throwable的子類,因此java.lang.Error和java.lang.Exception自身及其子類都可以作為throw的使用對象,如:throw new MyError();和throw new MyException();其中,MyError類是java.lang.Error的子類,MyException類是java.lang.Exception的子類。
2)不同點:java.lang.Error自身及其子類不需要try-catch語句的支持,可在任何時候將返回方法,如下面的方法定義:

?
1
2
3
public String myMethod() {
throw new MyError();
}

其中MyError類是java.lang.Error類的子類。
java.lang.Exception自身及其子類需要try-catch語句的支持,如下的方法定義是錯誤的:

?
1
2
3
public String myMethod() {
throw new MyException();
}

正確的方法定義如下:

?
1
2
3
public String myMethod() throws MyException {
throw new MyException();
}

其中MyException類是java.lang.Exception的子類。

JAVA異常是在java程序運行的時候遇到非正常的情況而創建的對象,它封裝了異常信息,java異常的根類為java.lang.Throwable,整個類有兩個直接子類java.lang.Error和java.lang.Exception.Error是程序本身無法恢復的嚴重錯誤.Exception則表示可以被程序捕獲并處理的異常錯誤.JVM用方法調用棧來跟蹤每個線程中一系列的方法調用過程,該棧保存了每個調用方法的本地信息.對于獨立的JAVA程序,可以一直到該程序的main方法.當一個新方法被調用的時候,JVM把描述該方法的棧結構置入棧頂,位于棧頂的方法為正確執行的方法.當一個JAVA方法正常執行完畢,JVM回從調用棧中彈處該方法的棧結構,然后繼續處理前一個方法.如果java方法在執行代碼的過程中拋出異常,JVM必須找到能捕獲異常的catch塊代碼.它首先查看當前方法是否存在這樣的catch代碼塊,如果存在就執行該 catch代碼塊,否則JVM回調用棧中彈處該方法的棧結構,繼續到前一個方法中查找合適的catch代碼塊.最后如果JVM向上追到了main()方法,也就是一直把異常拋給了main()方法,仍然沒有找到該異常處理的代碼塊,該線程就會異常終止,如果該線程是主線程,應用程序也隨之終止,此時 JVM將把異常直接拋給用戶,在用戶終端上會看到原始的異常信息.

Java.lang.throwable源代碼解析

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
package java.lang;
import java.io.*;
/**
*
* Throwable是所有Error和Exceptiong的父類
* 注意它有四個構造函數:
* Throwable()
* Throwable(String message)
* Throwable(Throwable cause)
* Throwable(String message, Throwable cause)
*
*/
public class Throwable implements Serializable {
  private static final long serialVersionUID = -3042686055658047285L;
 
  /**
  * Native code saves some indication of the stack backtrace in this slot.
  */
  private transient Object backtrace;
 
  /**
  * 描述此異常的信息
  */
  private String detailMessage;
 
  /**
  * 表示當前異常由那個Throwable引起
  * 如果為null表示此異常不是由其他Throwable引起的
  * 如果此對象與自己相同,表明此異常的起因對象還沒有被初始化
  */
  private Throwable cause = this;
 
  /**
  * 描述異常軌跡的數組
  */
  private StackTraceElement[] stackTrace;
 
  /**
  * 構造函數,起因對象沒有被初始化可以在以后使用initCause進行初始化
  * fillInStackTrace可以用來初始化它的異常軌跡的數組
  */
  public Throwable() {
   fillInStackTrace();
  }
 
  /**
  * 構造函數
  */
  public Throwable(String message) {
   //填充異常軌跡數組
   fillInStackTrace();
   //初始化異常描述信息
   detailMessage = message;
  }
 
  /**
  * 構造函數,cause表示起因對象
  */
  public Throwable(String message, Throwable cause) {
   fillInStackTrace();
   detailMessage = message;
   this.cause = cause;
  }
 
  /**
  * 構造函數
  */
  public Throwable(Throwable cause) {
   fillInStackTrace();
   detailMessage = (cause==null ? null : cause.toString());
   this.cause = cause;
  }
 
  /**
  * 獲取詳細信息
  */
  public String getMessage() {
   return detailMessage;
  }
 
  /**
  * 獲取詳細信息
  */
  public String getLocalizedMessage() {
   return getMessage();
  }
 
  /**
  * 獲取起因對象
  */
  public Throwable getCause() {
   return (cause==this ? null : cause);
  }
 
  /**
  * 初始化起因對象,這個方法只能在未被初始化的情況下調用一次
  */
  public synchronized Throwable initCause(Throwable cause) {
   //如果不是未初始化狀態則拋出異常
   if (this.cause != this)
    throw new IllegalStateException("Can't overwrite cause");
   
   //要設置的起因對象與自身相等則拋出異常
   if (cause == this)
    throw new IllegalArgumentException("Self-causation not permitted");
   
   //設置起因對象
   this.cause = cause;
   //返回設置的起因的對象
   return this;
  }
 
  /**
  * 字符串表示形式
  */
  public String toString() { 
   String s = getClass().getName();  
   String message = getLocalizedMessage(); 
   return (message != null) ? (s + ": " + message) : s;
  }
 
  /**
  * 打印出錯誤軌跡
  */
  public void printStackTrace() {
   printStackTrace(System.err);
  }
 
  /**
  * 打印出錯誤軌跡
  */
  public void printStackTrace(PrintStream s) {
   synchronized (s) {
   //調用當前對象的toString方法
    s.println(this);
   //獲取異常軌跡數組
    StackTraceElement[] trace = getOurStackTrace();
    
   //打印出每個元素的字符串表示
    for (int i=0; i < trace.length; i++)
    s.println("\tat " + trace[i]);
 
   //獲取起因對象
    Throwable ourCause = getCause();
    
   //遞歸的打印出起因對象的信息
    if (ourCause != null)
    ourCause.printStackTraceAsCause(s, trace);
   }
  }
 
  /**
  * 打印起因對象的信息
  * @param s 打印的流
  * @param causedTrace 有此對象引起的異常的異常軌跡
  */
  private void printStackTraceAsCause(PrintStream s,
           StackTraceElement[] causedTrace)
  {
   //獲得當前的異常軌跡
   StackTraceElement[] trace = getOurStackTrace();
   //m為當前異常軌跡數組的最后一個元素位置,
   //n為當前對象引起的異常的異常軌跡數組的最后一個元素
   int m = trace.length-1, n = causedTrace.length-1;
   //分別從兩個數組的后面做循環,如果相等則一直循環,直到不等或數組到頭
   while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
    m--; n--;
   }
   
   //相同的個數
   int framesInCommon = trace.length - 1 - m;
   
   //打印出不同的錯誤軌跡
   s.println("Caused by: " + this);
   for (int i=0; i <= m; i++)
    s.println("\tat " + trace[i]);
   //如果有相同的則打印出相同的個數
   if (framesInCommon != 0)
    s.println("\t... " + framesInCommon + " more");
 
   //獲得此對象的起因對象,并遞歸打印出信息
   Throwable ourCause = getCause();
   if (ourCause != null)
    ourCause.printStackTraceAsCause(s, trace);
  }
 
  /**
  * 打印出錯誤軌跡
  */
  public void printStackTrace(PrintWriter s) {
   synchronized (s) {
    s.println(this);
    StackTraceElement[] trace = getOurStackTrace();
    for (int i=0; i < trace.length; i++)
     s.println("\tat " + trace[i]);
 
    Throwable ourCause = getCause();
    if (ourCause != null)
     ourCause.printStackTraceAsCause(s, trace);
   }
  }
 
  /**
  * 打印起因對象的信息
  */
  private void printStackTraceAsCause(PrintWriter s,
           StackTraceElement[] causedTrace)
  {
   // assert Thread.holdsLock(s);
 
   // Compute number of frames in common between this and caused
   StackTraceElement[] trace = getOurStackTrace();
   int m = trace.length-1, n = causedTrace.length-1;
   while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
    m--; n--;
   }
   int framesInCommon = trace.length - 1 - m;
 
   s.println("Caused by: " + this);
   for (int i=0; i <= m; i++)
    s.println("\tat " + trace[i]);
   if (framesInCommon != 0)
    s.println("\t... " + framesInCommon + " more");
 
   // Recurse if we have a cause
   Throwable ourCause = getCause();
   if (ourCause != null)
    ourCause.printStackTraceAsCause(s, trace);
  }
 
  /**
  * 填充異常軌跡
  */
  public synchronized native Throwable fillInStackTrace();
 
  /**
  * 返回當前的異常軌跡的拷貝
  */
  public StackTraceElement[] getStackTrace() {
   return (StackTraceElement[]) getOurStackTrace().clone();
  }
 
  
  /**
  * 獲取當前的異常軌跡
  */
  private synchronized StackTraceElement[] getOurStackTrace() {
   //如果第一次調用此方法則初始化異常軌跡數組
   if (stackTrace == null) {
   //獲得異常軌跡深度
    int depth = getStackTraceDepth();
   //創建新的異常軌跡數組,并填充它
    stackTrace = new StackTraceElement[depth];
    
   for (int i=0; i < depth; i++)
    stackTrace[i] = getStackTraceElement(i);//獲取指定位標的異常軌跡
   }
   
   return stackTrace;
  }
 
  /**
  * 設置異常軌跡
  */
  public void setStackTrace(StackTraceElement[] stackTrace) {
   //拷貝設置參數
   StackTraceElement[] defensiveCopy =
    (StackTraceElement[]) stackTrace.clone();
   
   //如果設置參數有空元素則拋出異常
   for (int i = 0; i < defensiveCopy.length; i++)
    if (defensiveCopy[i] == null)
     throw new NullPointerException("stackTrace[" + i + "]");
 
   //設置當前對象的異常軌跡
   this.stackTrace = defensiveCopy;
  }
 
  /**
  * 異常軌跡的深度,0表示無法獲得
  */
  private native int getStackTraceDepth();
 
  /**
  * 獲取指定位標的異常軌跡
  */
  private native StackTraceElement getStackTraceElement(int index);
 
  
  private synchronized void writeObject(java.io.ObjectOutputStream s)
   throws IOException
  {
   getOurStackTrace();
   s.defaultWriteObject();
  }
}

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲一区二区三区在线播放 | 91麻豆制片厂 | 精品欧美一区二区在线观看欧美熟 | 日韩一区二区不卡 | 日韩美女强理论片 | 免费看视频高清在线观看 | 99re精品在线 | 日比免费视频 | 欧洲久久 | 99自拍网| 日本人成动漫网站在线观看 | 大象视频污 | 免费99精品国产自在现线 | 国产二区视频 | 三级理论在线播放大全 | 岛国片免费看 | 欧美在线视频一区在线观看 | 农村妇女野外牲交一级毛片 | 欧美日韩人成在线观看 | 国产在亚洲线视频观看 | 国产亚洲精品美女2020久久 | 爱情岛论坛亚洲自拍 | 久热这里只有精品99国产6 | 日韩欧美国产一区二区三区 | 女人张开腿让男人做爽爽 | 韩国三级做爰 | 成人免费网站视频ww | 欧美日韩精 | 九九在线精品亚洲国产 | 四虎在线视频免费观看 | 日本午夜影院 | 国产精品久久久久久搜索 | 女人把扒开给男人爽 | 久久影院中文字幕 | 色婷婷婷丁香亚洲综合不卡 | 精品视频免费在线 | 韩国禁片在线观看久 | 欧美最猛性xxxxx动态图 | xxxx18日本视频xxxxx | 无遮挡h肉动漫在线观看电车 | 四虎在线最新地址公告 |