我有一個可能會引發錯誤的方法。這個例外不在我的控制范圍內,因為它是一個 IO 例外,而不是我拋出的例外。除了向我的方法添加 throws 陳述句或將其放入 try 和 catch 塊中,我是否能夠通過此方法回傳一個可選項?
摘要:我有一個回傳值 T 的方法,除了要獲得該值,我必須在我的方法中添加一個 try/catch 塊或 throws 陳述句。我可以回傳 T 型別的 Optional 而不是拋出此錯誤嗎?
uj5u.com熱心網友回復:
“而不是在我的方法中添加 throws 陳述句或將其放入 try 和 catch 塊中”
好吧,這是你的兩個選擇。要么你可以
- 自己捕獲例外并回傳一個空的
Optional. 這不是一個好主意,因為它隱藏了例外,或者 - 您可以讓例外傳播。
- 我想第三種選擇是將例外包裝在未經檢查的例外中,但這只會使您的界面更加模糊。
如果你真的想把錯誤處理推遲到呼叫者而不是throw,理想的解決方案是實作一個復合物件來回傳,包含錯誤狀態和回傳值(如果有的話)。
uj5u.com熱心網友回復:
您可以使用這樣的代碼來包裝回傳值的代碼,其中包含捕獲例外并回傳空的可選內容:
import java.util.Optional;
import java.util.function.Supplier;
@FunctionalInterface
public interface ThrowingSupplier<T> extends Supplier<Optional<T>> {
@Override
default Optional<T> get() {
return getCapturingExceptions(this);
}
T getOrThrow() throws Exception;
static <U> Optional<U> getCapturingExceptions(ThrowingSupplier<U> supplier) {
try {
return Optional.ofNullable(supplier.getOrThrow());
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
}
使用示例:
import org.junit.Test;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
public class ThrowingSupplierTest {
@Test
public void testSuccessfulSupplier() {
assertEquals(
Optional.of("Successful"),
ThrowingSupplier.getCapturingExceptions(() -> "Successful")
);
}
@Test
public void testThrowingSupplier() {
assertEquals(
Optional.empty(),
ThrowingSupplier.getCapturingExceptions(() -> {
throw new Exception("Expected failure; will be logged but test should pass");
})
);
}
}
This has all of the disadvantages outlined in Jim Garrison's answer, and I would agree with him that it is usually better to allow exceptions to propagate (wrapping in an unchecked exception when necessary). Still, this is sometimes useful. For example, if you need to implement an interface that doesn't allow for a checked exception, and allowing an unchecked exception to propagate up the call stack would have undesirable effect such as killing a thread that doesn't handle them properly. To that end, this example implements Supplier (which cannot throw an unchecked exception) and can be used anywhere that interface is expected.
A few changes you might want to make:
This logs caught exceptions using
e.printStackTrace(). It is important not to completely lose the exception message and stack trace, but if your application uses a logging framework, you might prefer to log the exception using that.It uses
Optional.ofNullableon the assumption that the wrapped code might returnnull, which isn't allowed in anOptional. This means that it might return an emptyOptionaleven if no exception occurred. If the original code is not expected to returnnull, this could be changed toOptional.of. However if the wrapped code does returnnullin that case,Optional.ofwill throw aNullPointerException, which will be caught by thecatchblock and result in an emptyOptionalreturned regardless.
It should also be noted that if the wrapped code returns an Optional type itself, this will be wrapped in another Optional layer. Getting the underlying value will require unwrapping it twice.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/426248.html
