Простой ответ: нет.
От: Как создать список задач Список комментариев
Список задач отображает комментарии в вашем коде, которые начните с маркера комментария для вашего языка разработки. Рядом с комментариями в списке задач также отображается маркер задачи по умолчанию, такой как TODO, HACK или UNDONE или пользовательский токен комментария. Количество комментариев, отображаемых в списке задач, может изменяться в зависимости от типа проекта, над которым вы работаете. С Visual Basic и Visual C # в списке задач отображаются все комментарии в решении. С проектами Visual C ++ в списке задач отображаются только комментарии, которые находятся в файле, который в данный момент активен в редакторе.
Таким образом, он поддерживается только в проектах VB, C # и C ++.
Ниже представлен полный код класса Exceptional
. Он имеет довольно большой API, который является чистым расширением API Optional
, поэтому он может быть заменой для него в любом существующем коде, кроме того, что он не является подтипом конечного класса Optional
. Класс можно рассматривать как находящийся в том же соотношении с монадой Try
, поскольку Optional
находится с монадой Maybe
: он черпает вдохновение от него, но адаптирован к идиоме Java ( такие как фактические выбросы исключений даже из нетерминальных операций).
Это некоторые ключевые рекомендации, за которыми следует класс:
Класс пытается охватить все типичные способы обработки исключения:
recover
с некоторым кодом обработки, который обеспечивает заменяющее значение; flatRecover
, которое, аналогично flatMap
, позволяет вернуть новый экземпляр Exceptional
, который будет развернут, и состояние текущего экземпляра соответствующим образом обновлено; propagate
исключение, выкидывая его из выражения Exceptional
и делая вызов propagate
объявляющим этот тип исключения; propagate
после переноса в другое исключение ( translate it); handle
он, в результате чего пустым Exceptional
; swallow
он содержит пустой блок обработчика. Подход propagate
позволяет выборочно выбирать, какой че которые он хочет выставить из своего кода. Исключения, которые остаются необработанными во время вызова терминальной операции (например, get
), будут скрытно брошены без объявления. Это часто рассматривается как продвинутый и опасный подход, но тем не менее часто используется как способ немного облегчить неприятность проверенных исключений в сочетании с формами лямбды, которые не объявляют их. Класс Exceptional
надеется предложить более чистую и более избирательную альтернативу скрытому броску.
/*
* Copyright (c) 2015, Marko Topolnik. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class Exceptional<T>
{
private final T value;
private final Throwable exception;
private Exceptional(T value, Throwable exc) {
this.value = value;
this.exception = exc;
}
public static <T> Exceptional<T> empty() {
return new Exceptional<>(null, null);
}
public static <T> Exceptional<T> ofNullable(T value) {
return value != null ? of(value) : empty();
}
public static <T> Exceptional<T> of(T value) {
return new Exceptional<>(Objects.requireNonNull(value), null);
}
public static <T> Exceptional<T> ofNullableException(Throwable exception) {
return exception != null? new Exceptional<>(null, exception) : empty();
}
public static <T> Exceptional<T> ofException(Throwable exception) {
return new Exceptional<>(null, Objects.requireNonNull(exception));
}
public static <T> Exceptional<T> from(TrySupplier<T> supplier) {
try {
return ofNullable(supplier.tryGet());
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static Exceptional<Void> fromVoid(TryRunnable task) {
try {
task.run();
return new Exceptional<>(null, null);
} catch (Throwable t) {
return new Exceptional<>(null, t);
}
}
public static <E extends Throwable> Consumer<? super E> swallow() {
return e -> {};
}
public T get() {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw new NoSuchElementException("No value present");
}
public T orElse(T other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other;
}
public T orElseGet(Supplier<? extends T> other) {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
return other.get();
}
public Stream<T> stream() {
return value == null ? Stream.empty() : Stream.of(value);
}
public<U> Exceptional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (value == null) return new Exceptional<>(null, exception);
final U u;
try {
u = mapper.apply(value);
} catch (Throwable exc) {
return new Exceptional<>(null, exc);
}
return ofNullable(u);
}
public<U> Exceptional<U> flatMap(Function<? super T, Exceptional<U>> mapper) {
Objects.requireNonNull(mapper);
return value != null ? Objects.requireNonNull(mapper.apply(value)) : empty();
}
public Exceptional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (value == null) return this;
final boolean b;
try {
b = predicate.test(value);
} catch (Throwable t) {
return ofException(t);
}
return b ? this : empty();
}
public <X extends Throwable> Exceptional<T> recover(
Class<? extends X> excType, Function<? super X, T> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? ofNullable(mapper.apply(excType.cast(exception))) : this;
}
public <X extends Throwable> Exceptional<T> recover(
Iterable<Class<? extends X>> excTypes, Function<? super X, T> mapper)
{
Objects.requireNonNull(mapper);
for (Class<? extends X> excType : excTypes)
if (excType.isInstance(exception))
return ofNullable(mapper.apply(excType.cast(exception)));
return this;
}
public <X extends Throwable> Exceptional<T> flatRecover(
Class<? extends X> excType, Function<? super X, Exceptional<T>> mapper)
{
Objects.requireNonNull(mapper);
return excType.isInstance(exception) ? Objects.requireNonNull(mapper.apply(excType.cast(exception))) : this;
}
public <X extends Throwable> Exceptional<T> flatRecover(
Iterable<Class<? extends X>> excTypes, Function<? super X, Exceptional<T>> mapper)
{
Objects.requireNonNull(mapper);
for (Class<? extends X> c : excTypes)
if (c.isInstance(exception))
return Objects.requireNonNull(mapper.apply(c.cast(exception)));
return this;
}
public <E extends Throwable> Exceptional<T> propagate(Class<E> excType) throws E {
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public <E extends Throwable> Exceptional<T> propagate(Iterable<Class<? extends E>> excTypes) throws E {
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception))
throw excType.cast(exception);
return this;
}
public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
Class<E> excType, Function<? super E, ? extends F> translator)
throws F
{
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
Iterable<Class<E>> excTypes, Function<? super E, ? extends F> translator)
throws F
{
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception))
throw translator.apply(excType.cast(exception));
return this;
}
public <E extends Throwable> Exceptional<T> handle(Class<E> excType, Consumer<? super E> action) {
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public <E extends Throwable> Exceptional<T> handle(Iterable<Class<E>> excTypes, Consumer<? super E> action) {
for (Class<? extends E> excType : excTypes)
if (excType.isInstance(exception)) {
action.accept(excType.cast(exception));
return empty();
}
return this;
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) return value;
if (exception != null) sneakyThrow(exception);
throw exceptionSupplier.get();
}
public boolean isPresent() {
return value != null;
}
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
if (exception != null) sneakyThrow(exception);
}
public boolean isException() {
return exception != null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
return obj instanceof Exceptional && Objects.equals(value, ((Exceptional)obj).value);
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@SuppressWarnings("unchecked")
private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}
@FunctionalInterface
public interface TrySupplier<T> {
T tryGet() throws Throwable;
}
@FunctionalInterface
public interface TryRunnable {
void run() throws Throwable;
}
Что делать, если каждому функциональному интерфейсу, предоставленному java.util.function
, разрешено генерировать исключение?
public interface ThrowingSupplier<R, X extends Throwable> {
public R get() throws X;
}
Мы могли бы использовать некоторые методы по умолчанию для обеспечения желаемого поведения.
Я написал библиотеку , которая переопределяет большинство интерфейсов в java.util.function
таким образом. Я даже предоставляю ThrowingStream
, который позволит вам использовать эти новые интерфейсы с тем же API, что и обычный Stream
.
@FunctionalInterface
public interface ThrowingSupplier<R, X extends Throwable> {
public R get() throws X;
default public Supplier<R> fallbackTo(Supplier<? extends R> supplier) {
ThrowingSupplier<R, Nothing> t = supplier::get;
return orTry(t)::get;
}
default public <Y extends Throwable> ThrowingSupplier<R, Y> orTry(
ThrowingSupplier<? extends R, ? extends Y> supplier) {
Objects.requireNonNull(supplier, "supplier");
return () -> {
try {
return get();
} catch (Throwable x) {
try {
return supplier.get();
} catch (Throwable y) {
y.addSuppressed(x);
throw y;
}
}
};
}
}
( Nothing
- это RuntimeException
, который никогда не может быть брошен.)
Ваш исходный пример станет
ThrowingFunction<String, Integer, NumberFormatException> parse = Integer::parseInt;
Function<String, Optional<Integer>> safeParse = parse.fallbackTo(s -> null)
.andThen(Optional::ofNullable);
Stream.of(s1, s2)
.map(safeParse)
.map(i -> i.orElse(-1))
.forEach(System.out::println);
Существует сторонняя библиотека, названная better-java-monads . Он имеет Try
монаду, которая обеспечивает необходимые функции. Он также имеет функциональные интерфейсы TryMapFunction
и TrySupplier
для использования монады Try
с проверенными исключениями.
Either
и Try
. Они просто извергают ту же самую известную тему монад, которую я не нахожу особенно практичной вне Хаскелла. Они строго придерживаются религии чистого FP, безгражданства и неизменности. Почти все выражается как преобразование типа, которое подходит для такой мощной системы типа, как Haskell, намного лучше, чем Java. Кроме того, они не хорошо соединяются с остальной частью стандартной библиотеки и существующего кода; например, полностью обойдя систему исключений.
– Marko Topolnik
7 July 2015 в 17:52
Вот несколько обсуждений , которые я имел ранее в этой теме.
Я сделал интерфейс Result<T>
по рассуждениям. A Result<T>
является либо успешным со значением типа T
, либо неудачей с Исключением. Это подтип Async<T>
, как немедленное завершение асинхронного действия, но это не важно здесь.
Чтобы создать результат -
Result.success( value )
Result.failure( exception )
Result.call( callable )
Результат может быть преобразован различными способами - transform, map, then, peek, catch_, finally_
и т. д. Например
Async<Integer> rInt = Result.success( s )
.map( Integer::parseInt )
.peek( System.out::println )
.catch_( NumberFormatException.class, ex->42 ) // default
.catch_( Exception.class, ex-> { ex.printStacktrace(); throw ex; } )
.finally_( ()->{...} )
К сожалению, API фокусируется на Async, поэтому некоторые методы возвращают Async. Некоторые из них могут быть переопределены Результатом, чтобы вернуть результат; но некоторые не могут, например. then()
(это плоская карта). Однако, если интересно, легко извлечь автономный API результатов, который не имеет никакого отношения к Async.
finally_()
, поскольку любой предыдущий шаг, возможно, уже вызвал исключение. Чтобы сделать эту работу, вся реализация должна быть ленивой, просто помня о шагах, которые вы просили, а затем воспроизводите их в терминальной операции. Я также уверен, что подлый бросок никогда не найдет свой путь в API, как этот :)
– Marko Topolnik
7 July 2015 в 20:48
getOrThrow
. Мне нужно бросить с применением фильтра типа.
– Marko Topolnik
7 July 2015 в 20:59
Exceptional
внутри метода или внутри тела лямбды. Вы вызываете метод, получаете кучу проверенных исключений. Вы хотите распространять IOException
как проверенный, но кучу исключений отражения, которые вы просто хотите рассматривать как сбои.
– Marko Topolnik
7 July 2015 в 21:12
asList(Exception1.class, Exception2.class)
. – Marko Topolnik 7 July 2015 в 15:23X extends Throwable
, он предпочтет непроверенное исключение :it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type
– Jeffrey 7 July 2015 в 16:59expected
. Ожидается, что вexpected<exception, int>
будетint
, но если не причинаexception
. См. open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4015.pdf - он похож, но меньше связан с исключениями. – Yakk - Adam Nevraumont 7 July 2015 в 17:06