String
매개 변수가 있고를 반환하는 메서드에 대한 참조를 만드는 방법을 알고 있습니다 int
.
Function<String, Integer>
그러나 함수가 예외를 던지면 작동하지 않습니다.
Integer myMethod(String s) throws IOException
이 참조를 어떻게 정의합니까?
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
기본 방법을 사용할 수 있습니다 -아래 답변을 참조하십시오.
(String t) -> myWrappedMethod(t)
메소드 참조를 this::myWrappedMethod
사용할 수도 있습니다.
당신은 실제로 확장 할 수 있습니다 Consumer
(그리고 Function
자바 8의 사용 - 핸들 예외가있는 새로운 인터페이스 등)을 기본 방법을 !
이 인터페이스를 고려하십시오 (extends 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
예외를 발생시키는 일부 코드로 (예 : with )을 사용하려면 일반적으로 try / catch 블록을 설정했을 것입니다.
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)));
두리안의 Errors
수업 은 위의 다양한 제안의 많은 장점을 결합한 것 같습니다 .
프로젝트에 Durian을 포함 시키려면 다음 중 하나를 수행하십시오.
com.diffplug.durian:durian:3.3.0
Throwing.java
및Errors.java
면책 조항 : 아직 Java 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;
}
@FunctionalInterface
람다에 주석을 사용할 수 있도록 주석이 필요하지 않습니다. 그래도 위생 검사에 권장됩니다.
타사 라이브러리를 사용하지 않아도되는 경우 ( Vavr ) 다음을 작성할 수 있습니다.
CheckedFunction1<String, Integer> f = this::myMethod;
또한 오류를 처리하는 소위 Try 모나드가 있습니다.
Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
.map(i -> ...) // only executed on Success
...
더 읽어주세요 여기를 하십시오 .
면책 조항 : 저는 Vavr의 제작자입니다.
던지지 않은 래퍼를 사용할 수 있습니다
Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));
또는
Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);
그러나 아래와 같이 자신 만의 FunctionalInterface를 작성할 수 있습니다.
@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
void accept(T instance) throws X;
}
그런 다음 아래 표시된 것처럼 Lambdas 또는 참조를 사용하여 구현하십시오.
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");
}
}
할 수 있습니다.
@marcg를 확장 UtilException
하고 <E extends Exception>
필요한 곳에 generic을 추가 하십시오.이 방법으로 컴파일러는 throw 절과 모든 것을 Java 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 ()를 호출하는 대신 uncheckedNewInstanceForName ( "myClass")을 호출했습니다.
함수 래퍼를 사용하는 또 다른 솔루션은 결과의 래퍼 인스턴스를 반환하는 것입니다. 모든 것이 제대로 진행되면 성공이라고 말하고 실패라고합니다.
일을 명확히하는 코드 :
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
스트림에서 사용됩니다 (기본 Stream
뿐만 아니라 IntStream
, LongStream
및 DoubleStream
).
그리고 각각이 던지지 않는 상대를 확장함에 따라 람다에서도 직접 사용할 수 있습니다.
myStringStream.map(f) // <-- works
기본 동작은 던지는 람다가 확인 된 예외를 던지면 ThrownByLambdaException
확인 된 예외가 원인으로 발생합니다. 따라서이를 캡처하여 원인을 얻을 수 있습니다.
다른 기능도 사용할 수 있습니다.
@FunctionalInterface public interface SupplierWithCE<T, X extends Exception> { T get() throws X; }
-이 사용자가 캐치 할 필요가 없다 방법 Throwable
,하지만 특정 대신 예외를 확인했습니다.
ThrownByLambdaException
할 수 있습니다. 원래 예외가 원인이 될 수 있습니다 (또는 사용할 수 있습니다 rethrow(...).as(MyRuntimeException.class)
)
Throwing.runnable()
체인 기능을 사용 하여 다른 사용자도 사용할 수 있습니다.
여기에 이미 게시 된 훌륭한 답변이 많이 있습니다. 다른 관점에서 문제를 해결하려고합니다. 그것은 단지 2 센트입니다. 어딘가에 틀렸다면 수정하십시오.
FunctionalInterface의 Throws 절은 좋은 생각이 아닙니다
다음과 같은 이유로 IOException 발생을 강제하는 것이 좋지 않을 것이라고 생각합니다.
이것은 Stream / Lambda의 안티 패턴처럼 보입니다. 전체 아이디어는 호출자가 제공 할 코드와 예외 처리 방법을 결정한다는 것입니다. 많은 시나리오에서 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을 발생시킬 수도 있고 발생하지 않을 수도 있지만, FunctionalInterface 메소드의 throws 절로 인해 항상 시험해보십시오.
이 API가 IOException을 발생시키는 것을 알고 있다면 어떻게해야합니까
그렇다면 아마도 우리는 FunctionalInterface와 일반적인 인터페이스를 혼동하고있을 것입니다. 이 API가 IOException을 발생 시킨다는 것을 알고 있다면 대부분의 기본 / 추상 동작도 알고있을 것입니다. 다음과 같이 인터페이스를 정의하고 라이브러리를 기본 / 추상 구현으로 배포해야한다고 생각합니다.
public interface MyAmazingAPI {
Integer myMethod(String s) throws IOException;
}
그러나 try-catch 문제는 여전히 클라이언트에 존재합니다. 스트림에서 API를 사용하는 경우 여전히 끔찍한 try-catch 블록에서 IOException을 처리해야합니다.
다음과 같이 기본 스트림 친화적 인 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());
좋은가요? 물론 Exception :: printStackTrace 대신 로거 또는 기타 처리 로직을 사용할 수 있습니다.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function- 과 유사한 메소드를 노출 할 수도 있습니다 . 이전 메소드 호출의 예외를 포함 할 다른 메소드를 노출 할 수 있음을 의미합니다. 단점은 이제 API를 Stateful 상태로 만드는 것이므로 스레드 안전성을 처리해야하고 결국 성능에 영향을 줄 수 있습니다. 그래도 고려해야 할 옵션입니다.
Stream
발생한 요소를 알 수있는 방법이 없기 때문에 좋은 생각이 아닙니다 . 따라서 예외 처리기를 사용하고 유효하지 않은 결과를 필터링한다는 아이디어가 마음에 듭니다. MyAmazingAPI는 사실상 FunctionalInterface
(따라서 @FunctionalInterface 주석을 추가 할 수 있음) 유의하십시오 . 또한을 사용하는 대신 기본값을 사용할 수 Optional.empty()
있습니다.
몰래 던지는 관용구 는 CheckedException
Lambda 표현을 우회 할 수 있습니다 . a CheckedException
를 감싸는 것은 RuntimeException
엄격한 오류 처리에 좋지 않습니다.
Consumer
Java 콜렉션에서 사용되는 함수로 사용할 수 있습니다 .
다음은 지브의 대답에 대한 간단하고 개선 된 버전입니다 .
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);
}
}));
}
이 단지에서 람다 wrapps 다시 throw를 . 그것은 수 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;
}
}
이를 위해 ET 를 사용할 수 있습니다 . ET는 예외 변환 / 번역을위한 작은 Java 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의 저자입니다)
내가하고있는 일은 사용자가 예외의 경우 실제로 원하는 값을 줄 수 있도록하는 것입니다. 그래서 이런 식으로 뭔가를했습니다
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)
cyclops-react 와 함께 타사 라이브러리를 사용하는 것이 마음에 들지 않으면 FluentFunctions API를 사용하여 작성할 수 있습니다
Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);
ofChecked는 jOOλ CheckedFunction을 가져 와서 참조를 연화되지 않은 표준 JDK java.util.function.Function으로 되돌립니다.
또는 FluentFunctions API를 통해 캡처 된 기능을 계속 사용할 수 있습니다!
예를 들어, 메소드를 실행하고 최대 5 회 재 시도하고 기록 할 수있는 상태를 기록합니다.
FluentFunctions.ofChecked(this::myMethod)
.log(s->log.debug(s),e->log.error(e,e.getMessage())
.try(5,1000)
.apply("my param");
기본적으로 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
동일한 예외를 추가하십시오 .
확인 된 예외를 전파 할 사용자 정의 리턴 유형을 작성하십시오. 이는 기능 인터페이스의 메소드에서 "throws exception"을 약간 수정하여 기존 기능 인터페이스를 미러링하는 새 인터페이스를 작성하는 대안입니다.
public static interface CheckedValueSupplier<V> {
public V get () throws Exception;
}
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
클래스는 확인이 끝난 예외를 throw 어떤 논리를 실행 한 결과를 개최한다. 이렇게하면 코드가 인스턴스에 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
.
기능적인 인터페이스를 함께 피하고 좋은 for 루프를 사용하십시오.
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);
}
}
}
제공된 솔루션 중 일부는 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());
사용 Jool Library
또는 말 jOOλ library
에서JOOQ
. 검사되지 않은 예외 처리 인터페이스를 제공 할뿐만 아니라 Seq 클래스에 유용한 메소드를 많이 제공합니다.
또한 최대 16 개의 매개 변수가있는 기능 인터페이스가 포함되어 있습니다. 또한 다양한 시나리오에서 사용되는 Tuple 클래스를 제공합니다.
특히 org.jooq.lambda.fi.util.function
패키지의 라이브러리 조회에서 . 여기에는 Checked가 붙은 Java-8의 모든 인터페이스가 포함됩니다. 참조를 위해 아래를보십시오 :-
나는 어떤 자바 예외 를 잡거나 감싸지 않고도RuntimeException
어디서나 던질 수있는 일반적인 마술을 가진 작은 lib의 저자입니다 .
용법:
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);
}
}
}
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();
}
}
<code>/<code>
: : 대신 4 간격을 사용하여 프레젠테이션을 수정할 수 있습니다.