Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка? / 24 сообщений из 24, страница 1 из 1
04.09.2017, 19:24
    #39515312
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
04.09.2017, 20:06
    #39515334
Alexey Tomin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
04.09.2017, 20:58
    #39515350
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
...
Рейтинг: 0 / 0
04.09.2017, 22:28
    #39515371
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Прикольно. Я это понимаю следующим образом.

Код: 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
05.09.2017, 01:01
    #39515407
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
05.09.2017, 01:04
    #39515408
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Usmanredwhite90,

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

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

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

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


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

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


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

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

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

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

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


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

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


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

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

Почему он получается?
...
Рейтинг: 0 / 0
05.09.2017, 11:12
    #39515553
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
05.09.2017, 11:41
    #39515565
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Andrei T,

Спасибо, прямо вот всё понятно стало. от души просто.
...
Рейтинг: 0 / 0
05.09.2017, 11:54
    #39515581
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
redwhite90Спасибо, прямо вот всё понятно стало. от души просто.
Вот тут с объяснениями:
https://stackoverflow.com/a/31316879
...
Рейтинг: 0 / 0
05.09.2017, 12:54
    #39515614
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
05.09.2017, 13:10
    #39515631
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
redwhite90Чего-то пока не могу понять.это категория RuntimeException-ов, они считаются unchecked - не нужно их перечислять после ключевого слова throws
(это касается все исключения, которые были наследованы от RuntimeException)redwhite90Выглядит как какая-то багафича (:
...
Рейтинг: 0 / 0
05.09.2017, 13:20
    #39515638
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Usmanredwhite90Чего-то пока не могу понять.это категория RuntimeException-ов, они считаются unchecked - не нужно их перечислять после ключевого слова throws


Конечно это я знаю... не понятно как получилось так, что обошли обязанность прокидывать Exception
...
Рейтинг: 0 / 0
05.09.2017, 13:37
    #39515659
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
05.09.2017, 16:40
    #39515886
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
05.09.2017, 16:48
    #39515894
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
redwhite90да, мы обязаны декларировать Checked исключения, а все остальные не обязаны.это выглядит как бага?
...
Рейтинг: 0 / 0
05.09.2017, 16:54
    #39515902
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Usmanredwhite90да, мы обязаны декларировать Checked исключения, а все остальные не обязаны.это выглядит как бага?

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

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

Побочный эффект "стирания" generic'а:
- <E extends Throwable> трактуется как <RuntimeException>
- Кастинг t в RuntimeException не вызывает ClassCastException
- Стирание происходит во время компиляции, а также стирается сам кастинг и остается оригинальное исключение
...
Рейтинг: 0 / 0
05.09.2017, 19:06
    #39515967
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
06.09.2017, 05:22
    #39516100
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
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
06.09.2017, 09:13
    #39516149
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
Usman, я думал ты про типы после компиляции :)
...
Рейтинг: 0 / 0
07.09.2017, 12:08
    #39517234
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка?
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает трюк с пробросом checked exceptions для стримов с точки зрения языка? / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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