19

JCIPのセクション6.3.2によると:

Runnableはかなり限定的な抽象化です。runは、値を返したり、チェックされた例外をスローしたりすることはできません。

run()戻り型がvoidであるため、値を返すことはできませんが、チェックされた例外をスローできないのはなぜですか?

4

6 に答える 6

29

最初のバージョンからチェック例外をスローするように宣言されておらず、変更するには危険すぎるため、チェック例外をスローすることはできません。

元々Runnableはラップされたでのみ使用されてThreadいましたが、開発者は、にログを記録するのではなく、チェックされたすべての例外をキャッチして処理したいと考えていましたSystem.err

Callableスローされた例外Executorの結果をキャプチャできる場所に個々のタスクを追加できる場合に追加されました。Future

Callable値を返し、オプションでチェックされた例外を宣言できるようになりました。

ところで:呼び出し可能オブジェクトからの戻りやチェックされた例外のスローを望まないと言うことができる1つの方法は、次のようなものを使用することです。

Callable<Void> callable = new Callable<Void>() {
    public Void call() {
        // do something
        return null;
    }
};
于 2012-07-10T09:14:40.577 に答える
5

これは質問に対する答えではありません。むしろ、これはLukas Ederの回答のフォローアップであり、静的に許可されていない場所にチェック済みの例外を密輸する別の方法を示しています。newInstanceこれは、引数のないコンストラクターがで呼び出された場合、それがスローするチェックされた例外が上向きにエスケープされるという事実に依存しています。

public class Thrower {

    private static final ThreadLocal<Exception> toThrow = new ThreadLocal<Exception>();

    public static void throwUnsafely(Exception e) {
        try {
            toThrow.set(e);
            Thrower.class.newInstance();
        } catch (InstantiationException f) {
            throw new RuntimeException("unexpected exception while throwing expected exception", f);
        } catch (IllegalAccessException f) {
            throw new RuntimeException("unexpected exception while throwing expected exception", f);
        } finally {
            toThrow.remove();
        }
    }

    private Thrower() throws Exception {
        throw toThrow.get();
    }

}

これはクラスです-本当に古代の黒い帽子のJavaブードゥー。これを絶対に行わないでください。人々を感動させるパーティーを除いて。

于 2012-07-10T16:56:31.407 に答える
4

run()チェックされた例外をスローするように宣言されていないため、スローできません。チェックされた例外を宣言せずにスローすることはできません。

また、その例外をスローしない別のメソッドをオーバーライドまたは実装するメソッドで、チェックされた例外を宣言することはできません。したがって、の実装は、の実装に句をRunnable単純に追加することはできません。throwsrun()

于 2012-07-10T09:14:55.510 に答える
2

チェックされた例外をいつでも安全にスローできません。

import java.lang.reflect.Field;
import sun.misc.Unsafe;

public class UnsafeSample {
    public void methodWithNoDeclaredExceptions( ) {
        Unsafe unsafe = getUnsafe();
        unsafe.throwException( new Exception( "this should be checked" ) );
    }

    private Unsafe getUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main( String[] args ) {
        new UnsafeSample().methodWithNoDeclaredExceptions();
    }
}

ここで完全な記事を参照してください:

http://java.dzone.com/articles/throwing-undeclared-checked

別の選択肢:

public class Test {
    public static void main(String[] args) {
        doThrow(new SQLException());
    }

    public static void doThrow(Exception e) {
        Test.<RuntimeException> doThrow0(e);
    }

    @SuppressWarnings("unchecked")
    public static <E extends Exception> void doThrow0(Exception e) throws E {
        throw (E) e;
    }
}

これはここに示されています:

http://java.dzone.com/articles/throw-checked-exceptions

そうは言っても、やらないでください!;-)

于 2012-07-10T09:21:20.613 に答える
2

Runnable Interfaceを見ると、void run()メソッドがチェックされた例外をスローするものとして宣言されておらず、ThreadクラスがRunnableInterfaceを実装していることがわかります。

JLSによると、メソッドm1は、インターフェイス/スーパークラスで宣言されていない場合、例外をスローできません。

于 2012-07-10T09:25:50.227 に答える
2

Runnableで署名voidrun()を保持する背後にある動機は、他のメソッドのように呼び出されることを意図しておらず、代わりにCPUスレッドスケジューラによって呼び出されるように設計されていることだと思います。もしそうなら、誰がその戻り値を受け取り、誰がこれによってスローされたチェック例外を処理するのか。UncaughtExceptionHandlerは、スレッドによってスローされたキャッチされなかった例外を処理するためにJava5.0で提供されました。Executor Frameworkは、戻り値またはスローされた例外(ExecutionExceptionのラッパー)をスレッド間で共有されるオブジェクト(外部クラスインスタンスなど)の状態として保存し、Futureの呼び出し元(他のスレッドで実行されている)にそれらを提供します。get()。

于 2012-08-05T10:00:43.607 に答える