powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
24 сообщений из 24, страница 1 из 1
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515312
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Class.forName(className) throws ClassNotFoundException

ClassNotFoundException - checked

а мы хотим сделать цикл который по названия классов в массиве грузит их

На SO предлагают следующее
клиентский код(самое удивительное, что не надо писать throws в функции):
Код: java
1.
2.
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.Strin")
                .forEach(rethrowConsumer(className -> System.out.println(Class.forName(className))));


rethrowConsumer:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
 public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }



throwAsUnchecked:
Код: java
1.
2.
3.
4.
    @SuppressWarnings("unchecked")
    private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
        throw (E) exception;
    }



Выглядит как какой-то хак.

к чему кастим внутри throwAsUnchecked ?
Объясните плиз как так и из checked получается unchecked ?
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515334
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Class.forName(className) throws ClassNotFoundException

ClassNotFoundException - checked

а мы хотим сделать цикл который по названия классов в массиве грузит их

На SO предлагают следующее
клиентский код(самое удивительное, что не надо писать throws в функции):
Код: java
1.
2.
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.Strin")
                .forEach(rethrowConsumer(className -> System.out.println(Class.forName(className))));



rethrowConsumer:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
 public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }




throwAsUnchecked:
Код: java
1.
2.
3.
4.
    @SuppressWarnings("unchecked")
    private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
        throw (E) exception;
    }




Выглядит как какой-то хак.

к чему кастим внутри throwAsUnchecked ?
Объясните плиз как так и из checked получается unchecked ?

Ну как... При вызове У будет RuntimeException. Написать его прямо нельзя, поскольку тогда будет нормальное преобразование с проверкой. А E - без проверки (о чём "unchecked").
Да, хак. Работает.

По сути- это очередная демонстрация кривости концепции checked exceptions.
Используй Either .
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515350
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515371
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прикольно. Я это понимаю следующим образом.

Код: java
1.
2.
3.
4.
@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
    void accept(T t) throws E;
}


Вот эту часть кода вы пропустили, хотя она важна для понимания. Метод Consumer_WithExceptions#accept() объявляет, что он кидает нечто, что наследуется от Exception. Если этот метод где-то будет вызываться, то компилятор заставит нас написать обработку ошибки.

Код: java
1.
2.
3.
4.
@SuppressWarnings("unchecked")
static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
    throw (E) exception;
}


Здесь Exception превращается в нечто, что наследуется от Throwable (т.е. буквально "любая ошибка": Error, Exception или RuntimeException). Каст нужен, потому что E и Exception - это не один и тот же тип, и если не написать каст, то компилятор попросить объявить Exception в перечне выбрасываемых ошибок (т.е. дописать throws E, Exception). Каст разрешен, потому что upper bound E - это Throwable, и приведение Exception -> Throwable корректно. Но при этом каст небезопасный, так как компилятор не может знать, к чему реально будет привязан E в рантайме. При этом в данном случае это и неважно, поскольку то что выбрасывается через throw, можно присвоить к чему-то только через catch(), и если тип не совпадет, то вместо ClassCastException catch просто не будет вызван, т.е. программа никак не может спровоцировать некорректное приведение типов.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
    return t -> {
        try {
            consumer.accept(t);
        } catch (Exception exception) {
            throwAsUnchecked(exception);
        }
    };
}


Зная, что Consumer_WithExceptions#accept() кидает Exception, компилятор обязывает нас его как-то обработать. Перебросить мы его не можем, так как метод rethrowConsumer возвращает java.util.Consumer, у которого метод accept() уже не объявляет исключений. Т.е. единственный вариант это catch. Держим в уме, что помимо Exception любой метод может бросить RuntimeException или Error. Ни то, ни другое обработки не требует; при этом RuntimeException будет обработан в catch(Exception e), а Error вылетит, минуя обработку.

Код: java
1.
2.
3.
4.
public static void main(String[] args) {
        Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.Strin")
                .forEach(rethrowConsumer(className -> System.out.println(Class.forName(className))));
}


rethrowConsumer возвращает java.util.Consumer, что и требуется для Stream#forEach.

Код: java
1.
className -> System.out.println(Class.forName(className))


Тип лямбды в данном контексте вычисляется компилятором как Consumer_WithExceptions<String, ClassNotFoundException>, и поскольку метод rethrowConsumer компилируется, то это с т.з. компилятора значит, что ClassNotFoundException в нем корректно обрабатывается (и мы действительно видели, что внутри есть try{} catch(Exception), который перехватит ClassNotFoundException).

--

С моей точки зрения, такой код лучше не писать.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515407
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrei T,


Код: java
1.
void forEach(Consumer<? super T> action);



принимает уже консумера который ничего не бросает

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
 public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }



Пусть
Код: java
1.
consumer.accept(t);


это черный ящик

Все чекед и нечекед из него мы ловим

Код: java
1.
2.
3.
 } catch (Exception exception) {
     throwAsUnchecked(exception);
 }




Значит этот метод бросает то, что бросает

Код: java
1.
throwAsUnchecked(exception);


Код: java
1.
2.
3.
4.
    @SuppressWarnings("unchecked")
    private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
        throw (E) exception;
    }



Этот метод бросает некого наследника Throwable

почему мы не должны проверять его в вызывающем коде?
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515408
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90,

Прокачиваем Stream API, или нужно больше сахара

А что тут в этой ссылке по теме?
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515411
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90,

Тут работает автовыведение типов. Наверно, подразумевается, что если ошибка объявлена как некий наследник Throwable, то это может быть как checked, так и unchecked exception, и поэтому заставлять обрабатывать такую ошибку не следует.

Код: java
1.
throwAsUnchecked(exception);


E выводится как RuntimeException, о чем выше написал Alexey Tomin.

Если написать явно:
Код: java
1.
Main.<Exception>throwAsUnchecked(exception);


То потребуется написать обработку ошибки.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515421
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Usmanredwhite90,

Прокачиваем Stream API, или нужно больше сахара

А что тут в этой ссылке по теме?Толстый намек на то, что нужно extend-ить Stream и перегружать методы (ну, и скорее всего functional тоже).
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515540
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrei Tredwhite90,

Тут работает автовыведение типов. Наверно, подразумевается, что если ошибка объявлена как некий наследник Throwable, то это может быть как checked, так и unchecked exception, и поэтому заставлять обрабатывать такую ошибку не следует.

Код: java
1.
throwAsUnchecked(exception);


E выводится как RuntimeException, о чем выше написал Alexey Tomin.

Если написать явно:
Код: java
1.
Main.<Exception>throwAsUnchecked(exception);


То потребуется написать обработку ошибки.

То, что получается рантайм я и так вижу.

Почему он получается?
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515553
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Andrei Tredwhite90,

Тут работает автовыведение типов. Наверно, подразумевается, что если ошибка объявлена как некий наследник Throwable, то это может быть как checked, так и unchecked exception, и поэтому заставлять обрабатывать такую ошибку не следует.

Код: java
1.
throwAsUnchecked(exception);


E выводится как RuntimeException, о чем выше написал Alexey Tomin.

Если написать явно:
Код: java
1.
Main.<Exception>throwAsUnchecked(exception);


То потребуется написать обработку ошибки.

То, что получается рантайм я и так вижу.

Почему он получается?
http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.1.3
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515565
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrei T,

Спасибо, прямо вот всё понятно стало. от души просто.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515581
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Спасибо, прямо вот всё понятно стало. от души просто.
Вот тут с объяснениями:
https://stackoverflow.com/a/31316879
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515614
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

Так писать нельзя
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throw new Exception();
                //throwAsUnchecked(exception);
            }
        };
    }




а вот так можно:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
    public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
        return t -> {
            try {
                throw new Exception();
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }



То есть фишка в каком-то особенном выводе типов внутри throwAsUnchecked

Чего-то пока не могу понять. Выглядит как какая-то бага
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515631
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Чего-то пока не могу понять.это категория RuntimeException-ов, они считаются unchecked - не нужно их перечислять после ключевого слова throws
(это касается все исключения, которые были наследованы от RuntimeException)redwhite90Выглядит как какая-то багафича (:
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515638
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90Чего-то пока не могу понять.это категория RuntimeException-ов, они считаются unchecked - не нужно их перечислять после ключевого слова throws


Конечно это я знаю... не понятно как получилось так, что обошли обязанность прокидывать Exception
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515659
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90не понятно как получилось так, что обошли обязанность прокидывать Exceptionзадумка такая https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html The next question might be: "If it's so good to document a method's API, including the exceptions it can throw, why not specify runtime exceptions too?" Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515886
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90не понятно как получилось так, что обошли обязанность прокидывать Exceptionзадумка такая https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html The next question might be: "If it's so good to document a method's API, including the exceptions it can throw, why not specify runtime exceptions too?" Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.


Что Вы этим хотите сказать?

да, мы обязаны декларировать Checked исключения, а все остальные не обязаны.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515894
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90да, мы обязаны декларировать Checked исключения, а все остальные не обязаны.это выглядит как бага?
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515902
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanredwhite90да, мы обязаны декларировать Checked исключения, а все остальные не обязаны.это выглядит как бага?

Нет, багой выглядит то, что после хитрого каста генерика мы можем выплюнуть чекед эксепшн и не декларировать его нигде
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515958
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
redwhite90Usmanпропущено...
это выглядит как бага?

Нет, багой выглядит то, что после хитрого каста генерика мы можем выплюнуть чекед эксепшн и не декларировать его нигде https://dzone.com/articles/throw-checked-exceptions

Побочный эффект "стирания" generic'а:
- <E extends Throwable> трактуется как <RuntimeException>
- Кастинг t в RuntimeException не вызывает ClassCastException
- Стирание происходит во время компиляции, а также стирается сам кастинг и остается оригинальное исключение
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39515967
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Usmanredwhite90пропущено...


Нет, багой выглядит то, что после хитрого каста генерика мы можем выплюнуть чекед эксепшн и не декларировать его нигде https://dzone.com/articles/throw-checked-exceptions

Побочный эффект "стирания" generic'а:
- <E extends Throwable> трактуется как <RuntimeException>
- Кастинг t в RuntimeException не вызывает ClassCastException
- Стирание происходит во время компиляции, а также стирается сам кастинг и остается оригинальное исключение

На самом деле там остается не оригинальное исключение, а upper bound дженерика, т.е. Throwable:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
static <E extends java.lang.Throwable> void throwAsUnchecked(java.lang.Exception) throws E;
    descriptor: (Ljava/lang/Exception;)V
    flags: ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: athrow
      LineNumberTable:
        line 69: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       2     0 exception   Ljava/lang/Exception;
    Exceptions:
      throws java.lang.Throwable
    Signature: #68                          // <E:Ljava/lang/Throwable;>(Ljava/lang/Exception;)V^TE;



Для сравнения байткод Consumer_WithExceptions#accept():
Код: java
1.
2.
3.
4.
5.
6.
public abstract void accept(T) throws E;
    descriptor: (Ljava/lang/Object;)V
    flags: ACC_PUBLIC, ACC_ABSTRACT
    Exceptions:
      throws java.lang.Exception
    Signature: #8                           // (TT;)V^TE;



То что <E extends Throwable> трактуется как <RuntimeException>, это, как мне кажется, не побочный, а вполне намеренный эффект (не удивлюсь если где-нибудь в JLS это указано как special case). Логика по-видимому такая, что заставлять писать try{} catch (Throwable e){} некошерно, т.к. тогда код будет ловить все подряд, включая то, что ловить не следует.
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39516100
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrei TНа самом деле там остается не оригинальное исключение, а upper bound дженерика, т.е. Throwable:Все же остается оригинальное исключение ( не вложен и не запакован):
Код: java
1.
2.
3.
4.
5.
public static void main(String[] args) {
    throwUnchecked(new Exception("123"));
    throwUnchecked(new java.io.UnsupportedEncodingException("456"));
    throwUnchecked(new java.text.ParseException("789", 0));
}

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
Exception in thread "main" java.lang.Exception: 123
	at ...

Exception in thread "main" java.io.UnsupportedEncodingException: 456
	at ...

Exception in thread "main" java.text.ParseException: 789
	at ...
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39516149
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Usman, я думал ты про типы после компиляции :)
...
Рейтинг: 0 / 0
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
    #39517234
redwhite90
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]