IT이야기

Java 8 람다 함수는 예외를 발생시키는가?

cyworld 2022. 5. 19. 22:41
반응형

Java 8 람다 함수는 예외를 발생시키는가?

다음이 있는 방법에 대한 참조를 만드는 방법을 알고 있다.String매개 변수 및 반환int, 다음과 같다.

Function<String, Integer>

그러나 함수가 예외를 발생시킨다면 다음과 같이 정의된다.

Integer myMethod(String s) throws IOException

이 참조를 어떻게 정의하시겠습니까?

너는 다음 중 하나를 해야 할 것이다.

  • 코드가 맞는 경우, 선택한 예외를 선언하는 고유한 기능 인터페이스를 정의하십시오.

    @FunctionalInterface
    public interface CheckedFunction<T, R> {
       R apply(T t) throws IOException;
    }
    

    사용:

    void foo (CheckedFunction f) { ... }
    
  • 그렇지 않으면 포장Integer myMethod(String s)체크된 예외를 선언하지 않는 방법:

    public Integer myWrappedMethod(String s) {
        try {
            return myMethod(s);
        }
        catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    

    그 다음:

    Function<String, Integer> f = (String t) -> myWrappedMethod(t);
    

    또는:

    Function<String, Integer> f =
        (String t) -> {
            try {
               return myMethod(t);
            }
            catch(IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    

실제로 확장할 수 있음Consumer(그리고)Function등) Java 8의 기본 방법을 사용하여 예외를 처리하는 새 인터페이스 포함!

이 인터페이스를 고려하십시오(확장).Consumer):

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T elem) {
        try {
            acceptThrows(elem);
        } catch (final Exception e) {
            // Implement your own exception handling logic here..
            // For example:
            System.out.println("handling an exception...");
            // Or ...
            throw new RuntimeException(e);
        }
    }

    void acceptThrows(T elem) throws Exception;

}

그런 다음, 예를 들어 목록이 있는 경우:

final List<String> list = Arrays.asList("A", "B", "C");

사용하려는 경우(예: 와 함께)forEach) 예외를 발생시키는 일부 코드가 있는 경우, 전통적으로 시도/실행 블록을 설정했을 수 있음:

final Consumer<String> consumer = aps -> {
    try {
        // maybe some other code here...
        throw new Exception("asdas");
    } catch (final Exception ex) {
        System.out.println("handling an exception...");
    }
};
list.forEach(consumer);

그러나 이 새로운 인터페이스를 사용하면 람다 표현으로 인스턴스화할 수 있으며 컴파일러는 다음과 같이 불평하지 않을 것이다.

final ThrowingConsumer<String> throwingConsumer = aps -> {
    // maybe some other code here...
    throw new Exception("asdas");
};
list.forEach(throwingConsumer);

아니면 좀 더 간결하게 하기 위해 던지던가!

list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

업데이트: 두리안의 "오류"라는 아주 멋진 유틸리티 라이브러리 부분이 있는 것 같은데, 이것은 이 문제를 훨씬 더 유연하게 해결하는 데 사용될 수 있다.예를 들어, 위의 구현에서 오류 처리 정책을 명시적으로 정의했다.System.out...또는throw RuntimeException() 반면, Durian의 오류는 다양한 유틸리티 방법을 통해 정책을 즉시 적용할 수 있도록 한다.나눠줘서 고마워, @NedTwigg!

샘플 사용량:

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));

나는 두리안의 수업은 위의 다양한 제안들의 많은 장점들을 결합시킨다고 생각한다.

프로젝트에 Durian을 포함하려면 다음 중 하나를 수행하십시오.

  • 그것을 jcentermaven central 에서 잡는다.com.diffplug.durian:durian:3.3.0
  • 또는 코드에 두 개의 작은 클래스만 복사 붙여넣기:

이것은 자바 8에 특정되지 않는다.다음과 같은 내용을 컴파일하려고 하는 경우:

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}

고지 사항:나는 아직 자바 8을 사용하지 않았는데, 그것에 대해 읽기만 해.

Function<String, Integer>던지지 않다IOException, 그래서 당신은 그것에 어떤 코드도 넣을 수 없다.throws IOException. 만약 당신이 예상하는 방법을 부르고 있다면.Function<String, Integer>, 그러면 당신이 그 방법에 패스하는 람다는 던질 수 없다.IOException, 마침표.이렇게 람다를 쓸 수도 있다(내 생각에 이것은 확실하지 않지만 람다 구문인 것 같다):

(String s) -> {
    try {
        return myMethod(s);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
        // (Or do something else with it...)
    }
}

또는 람다를 전달하는 방법이 직접 작성한 방법이라면, 새로운 기능 인터페이스를 정의하여 매개 변수 유형으로 사용할 수 있다.Function<String, Integer>:

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}

제3자 리브(Vavr)를 사용해도 괜찮다면 글을 쓸 수 있다.

CheckedFunction1<String, Integer> f = this::myMethod;

또한 다음과 같은 오류를 처리하는 소위 Try monad도 가지고 있다.

Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
        .map(i -> ...) // only executed on Success
        ...

여기서 더 읽어보십시오.

고지 사항:나는 Vavr의 창조자다.

하지만 자신만의 기능을 만들 수 있다.아래와 같은 인터페이스를 발생시킨다.

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

그런 다음 아래 그림과 같이 람다 또는 참조를 사용하여 구현하십시오.

import java.io.FileWriter;
import java.io.IOException;

//lambda expressions and the execute around method (EAM) pattern to
//manage resources

public class FileWriterEAM  {
  private final FileWriter writer;

  private FileWriterEAM(final String fileName) throws IOException {
    writer = new FileWriter(fileName);
  }
  private void close() throws IOException {
    System.out.println("close called automatically...");
    writer.close();
  }
  public void writeStuff(final String message) throws IOException {
    writer.write(message);
  }
  //...

  public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {

    final FileWriterEAM writerEAM = new FileWriterEAM(fileName);    
    try {
      block.accept(writerEAM);
    } finally {
      writerEAM.close();
    }
  }

  public static void main(final String[] args) throws IOException {

    FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));

    FileWriterEAM.use("eam2.txt", writerEAM -> {
        writerEAM.writeStuff("how");
        writerEAM.writeStuff("sweet");      
      });

    FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);     

  }


 void writeIt() throws IOException{
     this.writeStuff("How ");
     this.writeStuff("sweet ");
     this.writeStuff("it is");

 }

}

던지지 않은 포장지를 사용할 수 있다.

Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));

또는

Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);

교활한 던지기 숙어로 우회 가능CheckedException람다 표현식의포장 aCheckedExceptionRuntimeException엄격한 오류 처리에는 좋지 않다.

자바 컬렉션에서 사용하는 함수로 사용할 수 있다.

여기에 지브의 답변이 간단하고 개선된 버전이 있다.

import static Throwing.rethrow;

@Test
public void testRethrow() {
    thrown.expect(IOException.class);
    thrown.expectMessage("i=3");

    Arrays.asList(1, 2, 3).forEach(rethrow(e -> {
        int i = e.intValue();
        if (i == 3) {
            throw new IOException("i=" + i);
        }
    }));
}

이것은 그저 람다를 다시 던져서 포장할 뿐이다.그것은 만든다.CheckedException아무거나 다시 던지다Exception네 람다에 던져진 거 말이야

public final class Throwing {
    private Throwing() {}

    @Nonnull
    public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
        return consumer;
    }

    /**
     * The compiler sees the signature with the throws T inferred to a RuntimeException type, so it
     * allows the unchecked exception to propagate.
     * 
     * http://www.baeldung.com/java-sneaky-throws
     */
    @SuppressWarnings("unchecked")
    @Nonnull
    public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
        throw (E) ex;
    }

}

여기에서 전체 코드 및 단위 테스트를 찾아보십시오.

넌 할 수 있다.

장장 @marcg의UtilException 및일일 추가 .<E extends Exception>필요한 경우: 이렇게 하면 컴파일러가 다시 던지기 조항을 추가하도록 강제할 것이고 모든 것은 마치 당신이 자바 8의 스트림에서 기본적으로 체크된 예외를 던질 수 있는 것과 같다.

public final class LambdaExceptionUtil {

    @FunctionalInterface
    public interface Function_WithExceptions<T, R, E extends Exception> {
        R apply(T t) throws E;
    }

    /**
     * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
     */
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E  {
        return t -> {
            try {
                return function.apply(t);
            } catch (Exception exception) {
                throwActualException(exception);
                return null;
            }
        };
    }

    @SuppressWarnings("unchecked")
    private static <E extends Exception> void throwActualException(Exception exception) throws E {
        throw (E) exception;
    }

}

public class LambdaExceptionUtilTest {

    @Test
    public void testFunction() throws MyTestException {
        List<Integer> sizes = Stream.of("ciao", "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
        assertEquals(2, sizes.size());
        assertEquals(4, sizes.get(0).intValue());
        assertEquals(5, sizes.get(1).intValue());
    }

    private Integer transform(String value) throws MyTestException {
        if(value==null) {
            throw new MyTestException();
        }
        return value.length();
    }

    private static class MyTestException extends Exception { }
}

Class.forName 및 Class.newInstance에 문제가 있어 람다에 다음을 수행했다.

public Object uncheckedNewInstanceForName (String name) {

    try {
        return Class.forName(name).newInstance();
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

람다 내에서 Class.forName("myClass")을 호출하는 대신 newInstance() 나는 방금 체크되지 않은 NewInstanceForName("myClass")을 호출했다.

선택한 예외를 전파하는 사용자 지정 반환 유형을 만드십시오.이는 기능 인터페이스의 방법에서 "스트로우 예외"를 약간 수정하여 기존의 기능 인터페이스를 미러링하는 새로운 인터페이스를 만드는 대안이다.

정의

CheckedValueSupplayer

public static interface CheckedValueSupplier<V> {
    public V get () throws Exception;
}

CheckedValue

public class CheckedValue<V> {
    private final V v;
    private final Optional<Exception> opt;

    public Value (V v) {
        this.v = v;
    }

    public Value (Exception e) {
        this.opt = Optional.of(e);
    }

    public V get () throws Exception {
        if (opt.isPresent()) {
            throw opt.get();
        }
        return v;
    }

    public Optional<Exception> getException () {
        return opt;
    }

    public static <T> CheckedValue<T> returns (T t) {
        return new CheckedValue<T>(t);
    }

    public static <T> CheckedValue<T> rethrows (Exception e) {
        return new CheckedValue<T>(e);
    }

    public static <V> CheckedValue<V> from (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            return Result.rethrows(e);
        }
    }

    public static <V> CheckedValue<V> escalates (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

사용법

//  Don't use this pattern with FileReader, it's meant to be an
//  example.  FileReader is a Closeable resource and as such should
//  be managed in a try-with-resources block or in another safe
//  manner that will make sure it is closed properly.

//  This will not compile as the FileReader constructor throws
//  an IOException.
    Function<String, FileReader> sToFr =
        (fn) -> new FileReader(Paths.get(fn).toFile());

// Alternative, this will compile.
    Function<String, CheckedValue<FileReader>> sToFr = (fn) -> {
        return CheckedValue.from (
            () -> new FileReader(Paths.get("/home/" + f).toFile()));
    };

// Single record usage
    // The call to get() will propagate the checked exception if it exists.
    FileReader readMe = pToFr.apply("/home/README").get();


// List of records usage
    List<String> paths = ...; //a list of paths to files
    Collection<CheckedValue<FileReader>> frs =
        paths.stream().map(pToFr).collect(Collectors.toList());

// Find out if creation of a file reader failed.
    boolean anyErrors = frs.stream()
        .filter(f -> f.getException().isPresent())
        .findAny().isPresent();

무슨 일이야?

체크된 예외를 발생시키는 단일 기능 인터페이스가 생성된다(CheckedValueSupplier점검된 예외를 허용하는 유일한 기능 인터페이스가 될 것이다. 인터페이스는 이 기지를 활용할 이다.CheckedValueSupplier확인된 예외를 발생시키는 모든 코드를 포장할 것.

CheckedValue클래스는 체크된 예외를 발생시키는 논리를 실행한 결과를 보유한다.이는 코드가 인스턴스가 지정한 값에 액세스를 시도하는 시점까지 체크된 예외의 전파를 방지한다.CheckedValue포함하다

이 접근법의 문제점들.

  • 우리는 지금 "예외"를 효과적으로 원래 던져진 구체적인 유형을 숨기고 있다.
  • 우리는 예외가 발생했다는 것을 알 수 없다.CheckedValue#get()라고 불린다.

컨슈머 외

일부 기능 인터페이스(Consumer예를 들어)는 반환 값을 제공하지 않으므로 다른 방식으로 취급해야 한다.

소비자 대신 기능

한 가지 접근방식은 스트림을 처리할 때 적용되는 소비자 대신 기능을 사용하는 것이다.

    List<String> lst = Lists.newArrayList();
// won't compile
lst.stream().forEach(e -> throwyMethod(e));
// compiles
lst.stream()
    .map(e -> CheckedValueSupplier.from(
        () -> {throwyMethod(e); return e;}))
    .filter(v -> v.getException().isPresent()); //this example may not actually run due to lazy stream behavior

에스컬레이션

또는 항상 다음 항목으로 에스컬레이션할 수 있음RuntimeException체크된 예외의 에스컬레이션을 포함하는 다른 답변이 있다.Consumer.

소비하지 마라.

기능적 인터페이스를 모두 사용하지 말고 루프에 대해 올이 좋은 방식을 사용하십시오.

함수 래퍼를 사용하는 또 다른 해결책은 결과의 포장지 인스턴스(instance)를 반환하는 것이다. "성공"이라고 말한다. 모든 것이 잘되면 "실패"라고 말한다.

명확히 하기 위한 일부 코드:

public interface ThrowableFunction<A, B> {
    B apply(A a) throws Exception;
}

public abstract class Try<A> {

    public static boolean isSuccess(Try tryy) {
        return tryy instanceof Success;
    }

    public static <A, B> Function<A, Try<B>> tryOf(ThrowableFunction<A, B> function) {
        return a -> {
            try {
                B result = function.apply(a);
                return new Success<B>(result);
            } catch (Exception e) {
                return new Failure<>(e);
            }
        };
    }

    public abstract boolean isSuccess();

    public boolean isError() {
        return !isSuccess();
    }

    public abstract A getResult();

    public abstract Exception getError();
}

public class Success<A> extends Try<A> {

    private final A result;

    public Success(A result) {
        this.result = result;
    }

    @Override
    public boolean isSuccess() {
        return true;
    }

    @Override
    public A getResult() {
        return result;
    }

    @Override
    public Exception getError() {
        return new UnsupportedOperationException();
    }

    @Override
    public boolean equals(Object that) {
        if(!(that instanceof Success)) {
            return false;
        }
        return Objects.equal(result, ((Success) that).getResult());
    }
}

public class Failure<A> extends Try<A> {

    private final Exception exception;

    public Failure(Exception exception) {
        this.exception = exception;
    }

    @Override
    public boolean isSuccess() {
        return false;
    }

    @Override
    public A getResult() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Exception getError() {
        return exception;
    }
}

간단한 사용 사례:

List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
    map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
    collect(Collectors.toList());

이 문제도 나를 괴롭히고 있다. 이것이 내가 이 프로젝트를 만든 이유다.

이를 통해 다음을 수행할 수 있다.

final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;

JDK에 의해 정의된 39개의 인터페이스로 구성된 토틀라가 있으며 이러한 인터페이스는Throwing등가; 그것들 모두@FunctionalInterface시냇물(기초)에 쓰이는 sStream하지만 또한IntStreamLongStream그리고DoubleStream).

그리고 각자가 던지지 않는 상대편을 확장하면 람다에서도 직접 사용할 수 있다.

myStringStream.map(f) // <-- works

기본 동작은 던지는 람다가 체크된 예외를 발생시킬 때ThrownByLambdaException점검된 예외를 원인으로 던져진다.그러므로 당신은 그것을 포착하고 원인을 얻을 수 있다.

다른 기능도 이용할 수 있다.

여기에 이미 많은 반응이 올라오고 있다.그냥 다른 관점으로 문제를 해결하려고 하는 것 뿐이야.그냥 내 2센트야, 내가 틀린 곳이 있으면 고쳐줘.

Functional(기능적)에서 절 던지기인터페이스는 좋은 생각이 아니다.

다음과 같은 이유로 인해 IOException을 강제 적용하는 것은 좋은 생각이 아니라고 생각한다.

  • 이것은 스트림/람바에 대한 안티패턴처럼 보인다.발신자가 어떤 코드를 제공할 것인지, 예외를 어떻게 처리할 것인지 결정한다는 것이 전체 생각이다.많은 시나리오에서 IOException은 클라이언트에 적용되지 않을 수 있다.예를 들어 클라이언트가 실제 I/O를 수행하는 대신 캐시/메모리로부터 값을 가져오는 경우.

  • 또한, 하천에서 취급하는 예외는 정말 끔찍하게 된다.예를 들어, 여기 내 코드가 너의 API를 사용하면

               acceptMyMethod(s -> {
                    try {
                        Integer i = doSomeOperation(s);
                        return i;
                    } catch (IOException e) {
                        // try catch block because of throws clause
                        // in functional method, even though doSomeOperation
                        // might not be throwing any exception at all.
                        e.printStackTrace();
                    }
                    return null;
                });
    

    못생겼지?더욱이, 내가 첫 번째 포인트에서 언급했듯이, doSomeOperation 방법은 (클라이언트/호출자의 구현에 따라) IOException을 던질 수도 있고 그렇지 않을 수도 있지만, 당신의 Functional(기능)에 있는 던지기 조항 때문에 그렇다.인터페이스 방법, 나는 항상 try-catch를 써야 한다.

이 API가 IOException을 발생시킨다는 사실을 알고 있는 경우 어떻게 해야 하는가?

  • 그렇다면 아마도 우리는 기능적 혼란을 겪고 있을 것이다.일반적인 인터페이스와의 인터페이스.만약 당신이 이 API가 IOException을 발생시킬 것이라는 것을 안다면, 아마도 당신은 약간의 디폴트/추상적인 행동도 알고 있을 것이다.인터페이스를 정의하고 (기본/추상 구현 시) 라이브러리를 다음과 같이 배포해야 한다고 생각한다.

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    }
    

    그러나 클라이언트에게는 여전히 try-catch 문제가 존재한다.내가 너의 API를 스트림에서 사용해도 IOException을 끔찍한 try-catch block에서 처리해야 해.

  • 다음과 같은 기본 스트림 친화 API 제공

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    
        default Optional<Integer> myMethod(String s, Consumer<? super Exception> exceptionConsumer) {
            try {
                return Optional.ofNullable(this.myMethod(s));
            } catch (Exception e) {
                if (exceptionConsumer != null) {
                    exceptionConsumer.accept(e);
                } else {
                    e.printStackTrace();
                }
            }
    
            return Optional.empty();
        }
    }
    

    기본 방법은 예외를 처리할 책임이 있는 소비자 개체를 인수로 간주한다.자, 고객 입장에서 볼 때 코드는 이렇게 보일 겁니다.

    strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace))
                    .filter(Optional::isPresent)
                    .map(Optional::get).collect(toList());
    

    멋지지?물론 예외:printStackTrace 대신 로거 또는 기타 취급 논리를 사용할 수 있다.

  • https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function-과 유사한 방법을 노출할 수도 있다. 이전 메서드 호출의 예외가 포함된 다른 메서드를 노출할 수 있다는 의미.단점은 현재 API를 상태 저장 상태로 만들고 있다는 것이며, 이는 스레드 안전을 처리해야 하며 결국 성능 히트작이 될 것이라는 것을 의미한다.그냥 고려해 볼만한 선택일 뿐이야.

기본적으로 Java 8 함수는 예외를 발생시키는 것을 허용하지 않으며, 복수의 답변에서 제시된 바와 같이 이를 달성할 수 있는 여러 가지 방법이 있다.

@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
    R apply(T t) throws E;
}

다음으로 정의:

private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
    if ("abc".equals(str)) {
        throw new IOException();
    }
  return 1;
};

그리고 덧붙인다.throws또는try/catch호출자 방식에서 동일한 예외.

나는 과부하 효용 함수를 사용한다.unchecked()여러 개의 사용 사례를 처리한다.


일부 예시 사용법

unchecked(() -> new File("hello.txt").createNewFile());

boolean fileWasCreated = unchecked(() -> new File("hello.txt").createNewFile());

myFiles.forEach(unchecked(file -> new File(file.path).createNewFile()));

지원 유틸리티

public class UncheckedUtils {

    @FunctionalInterface
    public interface ThrowingConsumer<T> {
        void accept(T t) throws Exception;
    }

    @FunctionalInterface
    public interface ThrowingSupplier<T> {
        T get() throws Exception;
    }

    @FunctionalInterface
    public interface ThrowingRunnable {
        void run() throws Exception;
    }

    public static <T> Consumer<T> unchecked(
            ThrowingConsumer<T> throwingConsumer
    ) {
        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };
    }

    public static <T> T unchecked(
            ThrowingSupplier<T> throwingSupplier
    ) {
        try {
            return throwingSupplier.get();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static void unchecked(
            ThrowingRunnable throwing
    ) {
        try {
            throwing.run();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

ET를 사용하면 된다.ET는 예외 변환/번역을 위한 작은 자바 8 라이브러리다.

ET를 사용하면 다음과 같이 보인다.

// Do this once
ExceptionTranslator et = ET.newConfiguration().done();

...

// if your method returns something
Function<String, Integer> f = (t) -> et.withReturningTranslation(() -> myMethod(t));

// if your method returns nothing
Consumer<String> c = (t) -> et.withTranslation(() -> myMethod(t));

ExceptionTranslator인스턴스는 여러 구성 요소에 의해 공유될 수 있는 안전한 스레드 입니다.더 규칙: 보다 더 구체적인 예외 변환 규칙)을 할 수 FooCheckedException -> BarRuntimeException ( 원하신다면.사용 가능한 다른 규칙이 없는 경우, 체크된 예외는 다음 계정으로 자동 변환됨RuntimeException.

(신고자:나는 ET의 저자)

만약 당신이 제3자 라이브러리를 사용해도 괜찮다면, 내가 기여하는 라이브러리인 Cyclops-react와 함께, 당신은 FluenceFunctions API를 사용하여 쓸 수 있다.

 Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);

OfChecked는 jOOλ CheckedFunction을 사용하고 부드러워진 참조를 표준(확인되지 않은) JDK java.util.function으로 되돌린다.함수

또는 FluxFunctions api를 통해 캡처된 기능으로 계속 작업할 수 있다!

예를 들어, 메서드를 실행하려면 최대 5번 재시도하고 상태를 기록하십시오.

  FluentFunctions.ofChecked(this::myMethod)
                 .log(s->log.debug(s),e->log.error(e,e.getMessage())
                 .try(5,1000)
                 .apply("my param");

내가 하는 일은 예외일 경우에 사용자가 실제로 원하는 가치를 줄 수 있도록 하는 것이다.그래서 나는 이런 모습을 하고 있다.

public static <T, R> Function<? super T, ? extends R> defaultIfThrows(FunctionThatThrows<? super T, ? extends R> delegate, R defaultValue) {
    return x -> {
        try {
            return delegate.apply(x);
        } catch (Throwable throwable) {
            return defaultValue;
        }
    };
}

@FunctionalInterface
public interface FunctionThatThrows<T, R> {
    R apply(T t) throws Throwable;
}

그리고 이것은 다음과 같이 불릴 수 있다.

defaultIfThrows(child -> child.getID(), null)

사용하다Jool Library말하거나 말하거나jOOλ library로부터JOOQ점검되지 않은 예외 처리 인터페이스를 제공할 뿐만 아니라 Seq 클래스에 많은 유용한 방법을 제공한다.

또한, 최대 16개의 매개변수를 가진 기능 인터페이스가 포함되어 있다.또한 다양한 시나리오에서 사용되는 튜플 클래스를 제공한다.

조올 깃 링크

특히 다음에 대한 라이브러리 검색에서org.jooq.lambda.fi.util.function predent가 되어 있다여기에는 Java-8의 모든 인터페이스가 포함되며, 미리 선택되어 있다.자세한 내용은 아래를 참조하십시오.

여기에 이미지 설명을 입력하십시오.

롬복이 있으면 @Sneaky로 방법에 주석을 달 수 있다.던지다

스니키던지는 조용히 삼키지 않고 런타임으로 싸운다.예외 또는 나열된 예외 유형의 예외를 수정하십시오.JVM은 체크된 예외 시스템의 일관성을 검사하지 않는다; javac은 그렇게 한다. 그리고 이 주석을 통해 당신은 그 메커니즘에서 벗어날 수 있다.

https://projectlombok.org/features/SneakyThrows

제안된 해결책들 중 몇몇은 던져지는 예외의 유형을 통과하기 위해 E의 일반적 인수를 사용한다.

한 걸음 더 나아가서 예외 유형의 소비자를 통과시키기 보다는 다음과 같이 예외 유형의 소비자를 통과하십시오.

Consumer<E extends Exception>

다음과 같은 여러 가지 재사용 가능한 변형을 만들 수 있다.Consumer<Exception>지원서의 일반적인 예외 처리 요구를 충족시킬 수 있을 것이다.

나는 뭔가 일반적인 것을 할 것이다:

public interface Lambda {

    @FunctionalInterface
    public interface CheckedFunction<T> {

        T get() throws Exception;
    }

    public static <T> T handle(CheckedFunction<T> supplier) {
        try {
            return supplier.get();
        } catch (Exception exception) {
            throw new RuntimeException(exception);

        }
    }
}

사용법:

 Lambda.handle(() -> method());

나는 어떤 Java Exception을 잡거나 포장할 필요 없이 아무 곳에나 던질 수 있는 어떤 일반적인 마법을 가진 작은 리브의 작가다.

사용량: unchecked(() -> methodThrowingCheckedException())

public class UncheckedExceptions {

    /**
     * throws {@code exception} as unchecked exception, without wrapping exception.
     *
     * @return will never return anything, return type is set to {@code exception} only to be able to write <code>throw unchecked(exception)</code>
     * @throws T {@code exception} as unchecked exception
     */
    @SuppressWarnings("unchecked")
    public static <T extends Throwable> T unchecked(Exception exception) throws T {
        throw (T) exception;
    }


    @FunctionalInterface
    public interface UncheckedFunction<R> {
        R call() throws Exception;
    }

    /**
     * Executes given function,
     * catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
     *
     * @return result of function
     * @see #unchecked(Exception)
     */
    public static <R> R unchecked(UncheckedFunction<R> function) {
        try {
            return function.call();
        } catch (Exception e) {
            throw unchecked(e);
        }
    }


    @FunctionalInterface
    public interface UncheckedMethod {
        void call() throws Exception;
    }

    /**
     * Executes given method,
     * catches and rethrows checked exceptions as unchecked exceptions, without wrapping exception.
     *
     * @see #unchecked(Exception)
     */
    public static void unchecked(UncheckedMethod method) {
        try {
            method.call();
        } catch (Exception e) {
            throw unchecked(e);
        }
    }
}

출처: https://github.com/qoomon/unchecked-exceptions-java

public void frankTest() {
    int pageId= -1;

    List<Book> users= null;
    try {
        //Does Not Compile:  Object page=DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> new Portal(rw.getInt("id"), "", users.parallelStream().filter(uu -> uu.getVbid() == rw.getString("user_id")).findFirst().get(), rw.getString("name")));

        //Compiles:
        Object page= DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> { 
            try {
                final Book bk= users.stream().filter(bp -> { 
                    String name= null;
                    try {
                        name = rw.getString("name");
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return bp.getTitle().equals(name); 
                }).limit(1).collect(Collectors.toList()).get(0);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return new Portal(rw.getInt("id"), "", users.get(0), rw.getString("name")); 
        } );
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

참조URL: https://stackoverflow.com/questions/18198176/java-8-lambda-function-that-throws-exception

반응형