2017-09-17 1 views
1

이것과 관련된 몇 가지 질문을 보았습니다 만 명확한 대답이 필요합니다. 나는 lamba 표현식이 실행되는 상황과 부작용의 개념을 이해하지만, 여기서 보지 못하는 해결 방법이 있다고 생각합니다.자바 8 스트림. lamba 표현식의 클라이언트 메소드에 예외를 던집니다.

성별에 따라 페르소나 목록을 매핑해야하지만, 내가 섹스를 결정하는 데 사용하는 방법은 Collectors.groupingBy가 좋아하는 것이 아닌 확인 된 예외를 반환합니다.

확인 된 예외를 제거하는 것은 옵션이 아니므로 코드 조각을 호출 한 클라이언트 메소드로 보내야합니다. 내가 할 수 있는게있어?

public class Example { 
    public static void main(String[] args) { 
    Example example = new Example(); 
    try { 
     example.runExample(); 
    } catch (MException e) { 
     //Place where I want to handle the exception 
    } 
    } 

    private void runExample() throws MException{ 
    List<Person> personas = Arrays.asList(new Person("Sergio", "234456789", 35), new Person("Mariana", "123456789", 38)); 
    Map<String, List<Person>> personsBySex = personas.stream().collect(Collectors.groupingBy(persona -> { 
     try { 
      return getSex(persona.getSSN()); 
     } catch (MException e) { 
     } 
     return null; 
     //Compiler forces me to return a value, but I don't want to return null. 
     //I want to throw up the MException to the client method (main) 
    })); 
    } 

    private String getSex(String ssn) throws MException { 
    // Imagine here is a call to an outside service that would give me the 
    // sex based on the SSN, but this service could return an exception as 
    // well 
    if (ssn.isEmpty()) 
     throw new MException(); 
    return ssn.startsWith("1") ? "Female" : "Male"; 
    } 
} 


class Person { 
    private String name, ssn; 
    private Integer age; 

    public Person(String name, String ssn, Integer age) { 
    this.name = name; 
    this.ssn = ssn; 
    this.age = age; 
    } 

    public String getName() {return name;} 
    public String getSSN() {return ssn;} 
    public Integer getAge() {return age;} 
} 

class MException extends Exception { 
} 

어떤 아이디어 주셔서 감사합니다!

+0

[이 질문] (https://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java -8-streams) 및 그 주석과 대답은 매우 흥미 롭습니다. Tl; dr : 예외를 처리해야하지만 아래의 답변과 연결된 질문 에서처럼 특정 패턴이나 Utils로 패턴을 숨길 수 있습니다. –

답변

3

해결되지 않은 조치로 체크 된 예외를 래핑하고 catch 블록에서 후자를 던지는 것이 대안 일 수 있습니다. 추가로 작업 할 수있는 원인으로 MException을 저장하고 있습니다.

private String getSexFriendly(String ssn) { 
    try { 
     return getSex(ssn); 
    } catch (MException e) { 
     throw new IllegalArgumentException(e); 
    } 
} 

비록 :

try { 
    return getSex(persona.getSSN()); 
} catch (MException e) { 
    throw new IllegalArgumentException(e); // choose a suitable runtime one 
} 

갈 수있는 또 다른 방법으로 상기 논리를 이동하는 Collectors.groupingBy 친화적 인 방법을 쓰는 것 (이전의 다소 수정을, 나는 그것을 좋아하지 않는다) 우리는 잘 생긴 람다해야합니다 : 귀하의 예외를 랩 잊어

persona -> getSexFriendly(persona.getSSN()) 
1

을 - 당신은 "비열한를 활용할 수있는 것은 발생 토륨 '생각하는 컴파일러를 속여을 가능하게하는 여기에 해킹 당신이 try-catch에 당신이했던 것처럼 예외를해야 할 것, 보통

public Integer toInteger(String string) throws IOException { 
    throw new IOException("whoopsie!"); 
} 

Stream.of("42") 
    .collect(Collectors.groupingBy(o -> toInteger(o))); // does not compile 

하지만 : - 귀하의 예외가 체크되어 있지에서이

이의이 문제를 다시 보자 자바 (8)에 소개 된 타입 추론 규칙을 이용 해결 방법이 있습니다 :

@Test 
public void example_1() throws Exception { 
    Stream.of("42") 
     .collect(Collectors.groupingBy(unchecked(this::toInteger))); 
} 

public Integer toInteger(String string) throws IOException { 
    throw new IOException("whoopsie!"); 
} 

private static <T, R> Function<T, R> unchecked(ThrowingFunction<T, R> f) { 
    return t -> { 
     try { 
      return f.apply(t); 
     } catch (Throwable thr) { 
      return ThrowingFunction.sneakyThrow(thr); 
     } 
    }; 
} 

public interface ThrowingFunction<T, R> { 
    R apply(T t) throws Throwable; 

    @SuppressWarnings("unchecked") 
    static <T extends Throwable, R> R sneakyThrow(Throwable t) throws T { 
     throw (T) t; 
    } 
} 

먼저 예외를 throw 할 수있는 함수를 나타내는 고유 한 함수 인터페이스를 만들어야합니다. 이 경우 ThrowingFunction입니다.

그런 다음 확인 된 람다를 표준 java.util.function으로 다시 패 키지하는 유틸리티 메소드를 생성 할 수 있습니다. 이 경우 unchecked().

마지막 단계는 부주의하게 예외를 throw하는 메서드를 만드는 것입니다. 이 경우 sneakyThrow().

실제로, 나는 이것에 관한 기사를 쓸 것이라고 생각합니다.

편집 : 은 내가 쓴 : 내가 찾은 http://4comprehension.com/sneakily-throwing-exceptions-in-lambda-expressions-in-java/

+0

여기에 기사에 대한 링크를 남기는 것을 잊지 마세요 +1 : – Andrew

+0

@AndrewTobilko는 상기시켜 주셔서 감사합니다 :) –