考慮JLS §18.1.3 - Bounds中的以下文章
在這里,當我們嘗試識別推理變數的界限集時 - 我們有以下情況之一:
...
- throws α:推理變數 α 出現在 throws 子句中。
...
throws α 形式的邊界純粹是資訊性的:它指導決議優化 α 的實體化,以便在可能的情況下,它不是檢查例外型別。
我認為這種說法是不正確的:
- 這是因為在理想情況下,提到 throws 子句是為了處理在代碼執行程序中可能發生的檢查例外。
- 那么為什么 JLS 仍然阻止α成為檢查例外呢?
- 理想情況下,推理變數 α必須限制為Checked 型別的例外,而不是Unchecked 變體。
我的理解是正確的還是我錯過了什么?
uj5u.com熱心網友回復:
我認為您對本宣告的解釋/理解有些誤導:
throws α 形式的邊界純粹是資訊性的:它指示決議優化 α 的實體化,以便在可能的情況下,它不是檢查的例外型別。
那條線指的是解決方案,據我了解,這不是關于在哪里throws α,而是關于在哪里α推斷,可以想象是方法的呼叫。
考慮這個類:
static class MyClass {
public static void main(String[] args) {
MyClass.<RuntimeException>something(0); // same as MyClass.something(1);
try {
MyClass.<IOException>something(2);
} catch (IOException ex) {
// checked exception
}
}
/**
* Will throw IOException if argument is 2, a RuntimeException otherwise
*/
static <T extends Exception> void something(int a) throws T {
if (a == 2) {
throw (T) new IOException(); //of course it's a bad cast
} else {
throw (T) new Exception();
}
}
}
分析完這兩個something方法后,重點關注方法中的呼叫main:
該呼叫MyClass.<IOException>something(0)需要一個 IOException。呼叫者知道它(假設完全記錄的合同而不是緊密耦合的代碼),并處理例外。
這已經告訴您該變數可以是已檢查例外,這與您的想法相反。
相反,該呼叫MyClass.<RuntimeException>something(0)基于類似的理由期望出現運行時例外。
如何推斷α(T在上面的示例中)允許編譯器跳過強制呼叫者捕獲/處理例外(如果要查看邊界,否則它必須這樣做)
extends Exception現在關于“優化”:可以合理地預期有界的型別變數會決議為已檢查的例外。但是,如果呼叫者知道它應該是一個運行時例外,它可以“通知”編譯器它將是一個運行時例外。這就是我通過RuntimeException在型別見證中指定所做的(RuntimeException當沒有明確給出型別引數時,它也是決議的型別)。
我們可以花幾天時間來解釋“優化”,但至少我作為呼叫者不必嘗試/捕獲呼叫,而且我仍然沒有擾亂編譯器(第一次呼叫)。
uj5u.com熱心網友回復:
考慮這個例子:
public class Main {
public static void main(String[] args) {
foo(() -> System.out.println("Foo"));
}
public static <T extends Exception> void foo(ThrowingRunnable<T> runnable) throws T {
runnable.run();
}
}
interface ThrowingRunnable<T extends Exception> {
void run() throws T;
}
T在呼叫時型別引數的推斷程序中foo,會在型別變數上系結一個“throws” T,T推斷為RuntimeException。如果不是因為這個界限,T就會被推斷為Exception因為這個T extends Exception界限。這意味著我需要做:
try {
foo(() -> System.out.println("Foo"));
catch (Exception e) {
// This won't be reached!
}
我必須處理例外,即使我在 lambda 中所做的只是列印東西!這似乎不太好,是嗎?
這個系結的目的是,如果方法沒有理由拋出受檢例外,它不會拋出受檢例外,這樣您就不必到處寫那么多 try...catch . 如果您執行以下操作,只會引發檢查例外foo:
foo(() -> new FileOutputStream("foo"));
如果系結的效果改為強制T成為檢查例外,那么它根本不會很有用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/427848.html
下一篇:TS2322:型別'(new()=>typeofRectangle)[]'不可分配給型別'Rectangle[]'
