Java 不满足条件例外;必须被抓住或宣布被抛出

Java 不满足条件例外;必须被抓住或宣布被抛出,java,lambda,Java,Lambda,我有一段代码,它需要在Lambda中抛出和异常: 公共静态消费者说唱者( 消费者,, 课程名称(clazz){ 返回i->{ 试一试{ 消费者。接受(i); }捕获(例外情况除外){ 试一试{ E exCast=分层铸造(ex); System.err.println( 发生异常:“+exCast.getMessage()); }捕获(ClassCastException ccEx){ 掷骰子; } } }; } publicstaticvoidprocessconditions(@NotNu

我有一段代码,它需要在Lambda中抛出和异常:

公共静态消费者说唱者(
消费者,,
课程名称(clazz){
返回i->{
试一试{
消费者。接受(i);
}捕获(例外情况除外){
试一试{
E exCast=分层铸造(ex);
System.err.println(
发生异常:“+exCast.getMessage());
}捕获(ClassCastException ccEx){
掷骰子;
}
}
};
}
publicstaticvoidprocessconditions(@NotNull列表条件)
抛出未满足的条件异常{
条件。forEach(
消费者说唱者(
实体条件->{
抛出新的未满足条件异常(entityCondition);
},unsatifiedConditionException.class));
}
即使采用这种方法,编译此文件也会引发错误:
unsatifiedconditionexception;必须捕获或声明要抛出


这里可能有什么问题或遗漏了什么?

如果您将lambda写成一个匿名类

new Consumer<EntityCondition>() {
  @Override public void accept(EntityCondition entityCondition) {
    throw new UnsatisfiedConditionException(entityCondition);
  }
}
。。。然后将其转换为消费者:

public static <T, E extends Exception> Consumer<T> consumerWrapper(
  ThrowingConsumer<T> consumer,
  Class<E> clazz) { ... }
公共静态消费者说唱者(
抛开消费者,
类clazz){…}

…除了你不能抛出ex,因为那样会再次破坏它。当不能抛出该异常时,您必须决定适当的行为。

必须将lambda视为匿名类

假设有一个名为
AbstractClass
的接口

public interface AbstractClass {
    void requestWork();
}
创建it的一个实现如下所示:

public static AbstractClass getImplementation() {
    return new AbstractClass() {
        @Override
        public void requestWork() {
            throw new Exception(); // <- javac: "Unhandled exception: java.lang.Exception"
        }
    };
}
public static AbstractClass getImplementation() {
    return () -> {
        throw new Exception();
    };
}
try {
    throw new Exception();
} catch (Exception e) {
    throw new RuntimeException(e);
}
编译器无法向重写的方法添加
throws
-声明,因为该方法是在抽象类中声明的

如何解决这个问题?您有三种选择:

  • 在lambda实现的类中添加throws声明
  • 使用
    try
    -
    catch
    语句处理lambda中的问题
  • 使用
    RuntimeException
    的子类,因为Java编译器不会强制您处理这些异常
  • 您还可以捕获异常并将其作为
    RuntimeException
    重新播放,如下所示:

    public static AbstractClass getImplementation() {
        return new AbstractClass() {
            @Override
            public void requestWork() {
                throw new Exception(); // <- javac: "Unhandled exception: java.lang.Exception"
            }
        };
    }
    
    public static AbstractClass getImplementation() {
        return () -> {
            throw new Exception();
        };
    }
    
    try {
        throw new Exception();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    

    别用你那闪亮的新锤子在吐司上涂黄油了。当然可以,但不是很好。在集合实例上调用
    forEach
    不是一个好主意,除非您已经从其他地方获得了lambda<代码>列表。forEach(x->{..})是错误的代码样式。Jst使用
    代替(varx:list){}
    。这些形式同样简短,对盲forEach没有任何性能优势,forEach有许多缺点,
    for
    没有:lambda不是(可变的)局部变量透明的,不是控制流透明的,也不是检查异常透明的。正如你所注意到的,所有严重的问题

    forEach on streams可以作为一系列
    map
    过滤器、
    flatMap
    等操作之后的最终终端操作。这不是一个全球性的“永远停止使用foreach!”!类似的事情

    是的,是的。回答我的问题 嘿,你的葬礼

    lambda在java中是无效的,除非在上下文中明确了它们要填充的功能接口。在本例中,它是
    ConsumerRapper
    的第一个参数(它没有任何用处,我马上就来讨论),这需要
    消费者
    。让我们看看消费者的定义:

    package java.util.function;
    
    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    }
    

    有一个非常明显的第四个选择你错过了:只是。。。。使用。。。。a代表(:)。是的。但他想知道编译器为什么会抱怨,以及如何解决这类问题,而不是在这种情况下最好的选择是什么。StackOverflow的问题通常包含代码,这些代码只是用来显示问题,而不是实际工作。