如果在類域的初始化程序中出現了例外,你將如何捕獲它?
例如:
class a{
int a = 1 / 0;
}
這里的例外發生在欄位級別。
我知道我可以做到:
class a {
a() {
try {
this.a = 1 / 0。
} catch (Throwable a) {}.
}
int a;
}
但只是出于好奇,是否可以在初始化欄位時進行?
額外的資訊。我問這個問題是因為在我最新的專案中,我有一個欄位想初始化為物件的新實體,如果只寫a = new Object();就好了,但我不能,因為該特定型別的建構式會拋出檢查過的例外。
uj5u.com熱心網友回復:
是否可以在初始化欄位的時候進行呢?
你可以定義一個方法:
class a {
int a = aValue()。
private int aValue() {
try
{
return 1/0;
}
catch (Throwable a){
//...但是現在你需要回傳一些東西,或者(重新)拋出一個例外。 }
}
}
}
或者使用實體初始化器:
class a {
int a;
{
try
{
this.a=1/0。
}
catch (Throwable a){
//你不需要在這里做任何事情,除非`a`是`final`。 }
}
}
}
但是請注意,實體初始化器是行內到建構式中的(或者,至少是任何顯式或隱式呼叫super(...)的建構式,而不是this(...)),所以這實際上與問題中把它放在建構式中是一樣的。
uj5u.com熱心網友回復:
要抓住這些真的很難。因此,我們強烈建議確保靜態初始化器不拋出任何我們可能想要捕捉的東西。(例如,拋出OutOfMemoryError是可以的,但不可能有人想寫代碼來捕獲這個錯誤,并采取其他路徑或試圖解決問題)。
這通常是通過將你的靜態初始化器替換為方法呼叫來開始的。替換:
static int a; static {a = 1/0; }
與:
static int a = calculateA()。
private static int calculateA() {
return 1/0;
}
當然,這只是路徑上的一個步驟。將初始化代碼(calculateA方法)移到一個單獨的類中,現在你可以單獨測驗它,甚至不會遇到在類的靜態初始化程序中捕捉例外的問題。
一旦你解決了這個問題,你就可以使用這個 "技巧 "來轉移問題。想象一下,a的值對于這個類中的兩個方法是必需的。然后,"推遲 "這個例外:
public class Example {
private static final int a。
private static final Throwable aProblem;
static {
int a = 0;
Throwable aProblem = null;
try {
a = calculateA();
} catch (RuntimeException e) {
aProblem = e;
}
Example.a = a;
Example.aProblem = aProblem;
}
private static int calculateA() { return 1/0; }
public static void apiMethodUsingA1(){
if (aProblem != null) throw aProblem。
return a;
}
public static void apiMethodUsingA2() {
if (aProblem != null) throw aProblem。
return a 5;
}
如果這些選項都不可用,例如因為A不是你寫的,而且不能改變,那么你必須將A類委托給 "糟糕的API/蹩腳的庫",并且你要做你在面對這樣的庫時經常做的事情。繞過它,接受你需要撰寫難以維護/丑陋的代碼的事實,如果它真的很糟糕,就撰寫一個包裝器來隔離問題。甚至可以使用反射。
這是將例外隔離到代碼塊中的一個有保障的方法:
這是將例外隔離到代碼塊中的一個有保障的方法。
package com.foo;
class Example {
static int a = 1/0;
}
class Main {
public static void main title function_">main(String[] args) throws Exception {
try {
Class<?> c = Class.forName("com.foo.Example") 。
} catch (ExceptionInitializerError e) {
System.err.println("Hey I caught it")。
Throwable actualException = e.getCause()。
///在這里做一些處理。
actualException.printStackTrace(); //not this - this is for debugging only!
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/333050.html
標籤:
