Подтвердить что ты не робот

Почему не удается запустить() Runnable throw checked Exceptions?

В соответствии с разделом 6.3.2 JCIP:

Runnable - довольно лимитирующая абстракция; run не может вернуть значение или исключить исключенное исключение.

run() не может вернуть значение, так как его тип возврата недействителен, но почему он не может выставить проверенное исключение?

4b9b3361

Ответ 1

Он не может выставить проверенное исключение, потому что оно не было объявлено как бросание проверенного исключения из первой версии, и это слишком опасно для его изменения.

Первоначально Runnable использовался только в завернутом Thread, и предполагалось, что разработчик захочет поймать все проверенные исключения и обработать их, а не записывать их в System.err.

Callable был добавлен, когда вы можете добавить отдельные задачи в Executor, где вы можете записать результат в Future и любое исключенное исключение.

Callable теперь позволяет вам вернуть значение и необязательно объявить исключенное исключение.

BTW. Один из способов сказать, что вы не хотите возврата или выбрасывать исключенное исключение из вызываемого - использовать что-то вроде

Callable<Void> callable = new Callable<Void>() {
    public Void call() {
        // do something
        return null;
    }
};

Ответ 2

Это не ответ на вопрос. Скорее, это ответ 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 voodoo. Никогда не делай этого. За исключением сторон, чтобы произвести впечатление на людей.

Ответ 3

run() не может выставить проверенное исключение, потому что оно не объявлено для этого. Вы не можете бросить проверенные исключения, не объявляя их.

Вы также не можете объявлять проверенные исключения для метода, который переопределяет или реализует другой метод, который не генерирует это исключение. Таким образом, реализации Runnable не могут просто добавить предложения throws к их реализациям run().

Ответ 4

Вы всегда можете исключить проверенные исключения:

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

Сказав это, не делайте этого!; -)

Ответ 5

Если вы посмотрите на Runnable Interface, вы обнаружите, что метод void run() не объявлен как бросающий любое проверенное исключение, а ваш класс Thread реализует Runnable Интерфейс.

JLS говорит, что метод m1 не может генерировать исключение, если в интерфейсе/суперклассе он не объявлен.

Ответ 6

Я думаю, что мотивация сохранения функции void run() в Runnable заключается в том, что она не предназначена для вызова, как и другие методы, вместо этого она предназначена для вызова планировщика потоков процессора. Если да, то кто будет получать свою возвращаемую стоимость и кто будет справляться с этим брошенным исключением. UncaughtExceptionHandler пришел в Java 5.0 для обработки исключенных исключений, созданных потоком. Executor Framework сохраняет возвращаемое значение или исключенное исключение (оболочка в ExecutionException) в качестве состояний некоторого объекта, разделенного по потокам (например, экземпляр класса Outer), и очищает их от вызывающего (кто работает в каком-то другом потоке) будущего. get().