Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8流。向lamba表达式内的客户端方法抛出异常_Java_Lambda_Java 8_Java Stream - Fatal编程技术网

Java8流。向lamba表达式内的客户端方法抛出异常

Java8流。向lamba表达式内的客户端方法抛出异常,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我看到了一些与此相关的问题,但我需要一个明确的答案。我确实理解lamba表达式运行的上下文,以及副作用的概念,但我相信有一个解决方法我在这里没有看到 我需要根据人物角色的性别映射一个列表,但是我用来确定他们性别的方法返回一个选中的异常,这根本不是Collectors.groupingBy喜欢的 清除选中的异常不是一个选项,我需要将它发送给调用我的代码片段的客户机方法。我能做点什么吗 public class Example { public static void main(String[]

我看到了一些与此相关的问题,但我需要一个明确的答案。我确实理解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 {
}
公共类示例{
公共静态void main(字符串[]args){
示例=新示例();
试一试{
runExample();
}捕获(MException e){
//我要处理异常的位置
}
}
private void runExample()引发MeException{
listpersonas=Arrays.asList(新人(“塞尔吉奥”,“234456789”,35),新人(“玛丽安娜”,“123456789”,38));
Map personsBySex=personas.stream().collect(Collectors.groupingBy(persona->{
试一试{
返回getSex(persona.getSSN());
}捕获(MException e){
}
返回null;
//编译器强制我返回一个值,但我不想返回null。
//我想向客户机方法抛出MException(main)
}));
}
私有字符串getSex(字符串ssn)抛出MException{
//想象一下,这是一个打给外部服务的电话,它会给我
//sex基于SSN,但此服务可能会返回异常作为
//嗯
if(ssn.isEmpty())
抛出新的MException();
返回ssn.startsWith(“1”)?“女性”:“男性”;
}
}
班主任{
私有字符串名称,ssn;
私人整数年龄;
公众人物(字符串名称、字符串ssn、整数年龄){
this.name=名称;
这个.ssn=ssn;
这个。年龄=年龄;
}
公共字符串getName(){return name;}
公共字符串getSSN(){return ssn;}
公共整数getAge(){return age;}
}
类MException扩展了异常{
}

谢谢你的建议

解决方法可以是将选中的异常包装为未选中的异常,然后从
catch
块中抛出后者。请注意,我们正在保存一个
MException
,以便能够进一步处理

try {
    return getSex(persona.getSSN());
} catch (MException e) {
    throw new IllegalArgumentException(e); // choose a suitable runtime one
}
另一种方法是编写一个
收集器。groupingBy
-友好的方法将上述逻辑转换为:

private String getSexFriendly(String ssn) {
    try {
        return getSex(ssn);
    } catch (MException e) {
        throw new IllegalArgumentException(e);
    }
}
不过,我们会有一个好看的兰姆达:

persona -> getSexFriendly(persona.getSSN())

解决方法可以是将选中的异常包装为未选中的异常,然后从
catch
块抛出后者。请注意,我们正在保存一个
MException
,以便能够进一步处理

try {
    return getSex(persona.getSSN());
} catch (MException e) {
    throw new IllegalArgumentException(e); // choose a suitable runtime one
}
另一种方法是编写一个
收集器。groupingBy
-友好的方法将上述逻辑转换为:

private String getSexFriendly(String ssn) {
    try {
        return getSex(ssn);
    } catch (MException e) {
        throw new IllegalArgumentException(e);
    }
}
不过,我们会有一个好看的兰姆达:

persona -> getSexFriendly(persona.getSSN())

忘记包装您的异常-您可以利用这里的“偷偷抛出”攻击,这使您能够欺骗编译器认为您的异常未被检查-这利用了Java 8中引入的类型推断规则

让我们重新创建您的问题:

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

Stream.of("42")
  .collect(Collectors.groupingBy(o -> toInteger(o))); // does not compile
通常,您需要像以前一样尝试捕获异常,但是有一个解决方法:

@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;
    }
}
@测试
public void示例_1()引发异常{
第42流(“42”)
.collect(收集器.groupingBy(未选中(this::toInteger));
}
公共整数toInteger(字符串)引发IOException{
抛出新IOException(“哇!”);
}
未选中私有静态函数(ThrowingFunction f){
返回t->{
试一试{
返回f.apply(t);
}捕获(可丢弃的thr){
返回ThrowingFunction.Skillythrow(thr);
}
};
}
公共接口功能{
R应用(T)可丢弃;
@抑制警告(“未选中”)
静态R潜行(可丢弃的t)抛出t{
投掷(T)T;
}
}
首先,您需要创建自己的函数接口来表示可以抛出异常的函数

然后,您可以创建一个实用程序方法,将选中的lambda重新打包为标准的
java.util.function
。在本例中,
unchecked()

最后一步是创建一个偷偷抛出异常的方法

事实上,我想我会写一篇关于这个的文章

编辑:
我写道:

忘了包装你的异常-你可以利用这里的“偷偷抛出”技巧,让你欺骗编译器认为你的异常没有被检查-这利用了Java 8中引入的类型推断规则

让我们重新创建您的问题:

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

Stream.of("42")
  .collect(Collectors.groupingBy(o -> toInteger(o))); // does not compile
通常,您需要像以前一样尝试捕获异常,但是有一个解决方法:

@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;
    }
}
@测试
public void示例_1()引发异常{
第42流(“42”)
.collect(收集器.groupingBy(未选中(this::toInteger));
}
公共整数toInteger(字符串)引发IOException{
抛出新IOException(“哇!”);
}
未选中私有静态函数(ThrowingFunction f){
返回t->{
试一试{
返回f.apply(t);
}捕获(可丢弃的thr){
返回ThrowingFunction.Skillythrow(thr);
}
};
}
公共接口功能{
R应用(T)可丢弃;
@抑制警告(“未选中”)
静态R潜行(可丢弃的t)抛出t{
投掷(T)T;
}
}
首先,您需要创建自己的函数接口来表示可能引发异常的函数。在这种情况下,
throwing函数

然后,您可以创建一个实用程序方法来重新打包y