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
자바 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
수업 은 위의 다양한 제안의 많은 장점을 결합한 것 같습니다 .
- 던지는 함수를 표준 Java 8 기능 인터페이스로 랩하십시오.
- 오류 처리를위한 다양한 정책을 쉽게 지정
- 값을 반환하는 메서드를 래핑 할 때 기본값을 지정하거나 RuntimeException을 다시 throw하는 것에 는 중요한 차이점 이 있습니다.
- Java 8 기능 인터페이스
- fge의 답변과 유사
- 특정 예외를 던지기위한 표준 인터페이스
- 어떤 주소 졸탄의 우려를
프로젝트에 Durian을 포함 시키려면 다음 중 하나를 수행하십시오.
- jcenter 또는 maven central 에서 가져 가십시오 .
com.diffplug.durian:durian:3.3.0
- 아니면 그냥 코드에 단지 두 개의 작은 클래스를 붙여 복사
Throwing.java
및Errors.java
답변
이것은 Java 8에만 국한된 것이 아닙니다. 다음과 동등한 것을 컴파일하려고합니다.
interface I {
void m();
}
class C implements I {
public void m() throws Exception {} //can't compile
}
답변
면책 조항 : 아직 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;
}
답변
타사 라이브러리를 사용하지 않아도되는 경우 ( 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);