JAVA Consumer throws an exception

There was no problem with this code at the beginning, but after it was put into production, it was found that some abnormal data caused the server to report an error, but the front desk still returned the operation successfully. After checking the bug , it was found that the exception was eaten by the caller. The reason is that the original Consumer does not support it. Exception throwing can only be handled internally. After receiving feedback, it can indeed be reproduced by self-testing. Checking the source code of Consumer, it is found that throwing is not supported natively. Checking the network information, it is found that only one Consumer method can be rewritten, so hereby record it

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);//并没有异常处理

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Solution:

  1. Create a new ThrowingConsumer.class file
import java.util.function.Consumer;

/**
 * @ClassName: ThrowingConsumer
 * @Description: 重写Java8的Consumer中的异常抛出
 * @author:Erwin.Zhang
 * @date: 2021-03-01 10:59:19
 */
@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T e) {
        try {
            accept0(e);
        } catch (Throwable ex) {
            Throwing.sneakyThrow(ex);
        }
    }

    void accept0(T e) throws Throwable;

}

Create a new Throwing.class that handles exceptions

import javax.validation.constraints.NotNull;

* @ClassName: Throwing
* @Description: 在Java8的Consumer中抛出异常
* @author:Erwin.Zhang
* @date: 2021-03-01 10:58:31
 */
public class Throwing {
    private Throwing() {}

    @NotNull
    public static <T> Consumer<T> rethrow(@NotNull 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")
    @NotNull
    public static <E extends Throwable> void sneakyThrow(@NotNull final Throwable ex) throws E {
        throw (E)ex;
    }
}

Instructions

import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException;

* @ClassName: ThrowingTest
* @Description: 测试异常抛出
* @author:Erwin.Zhang
* @date: 2021-03-01 11:00:38
 */
public class ThrowingTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testRethrow() {
        thrown.expect(IOException.class);
        thrown.expectMessage("i=3");

        Arrays.asList(1, 2, 3).forEach(rethrow(e -> {
            int i = e;
            if (i == 3) {
                throw new IOException("i=" + i);
            }
        }));
    }

    @Test(expected = IOException.class)
    public void testSneakyThrow() {
        Throwing.sneakyThrow(new IOException());
    }

    @Test
    public void testThrowingConsumer() {
        thrown.expect(IOException.class);
        thrown.expectMessage("i=3");

        Arrays.asList(1, 2, 3).forEach((ThrowingConsumer<Integer>)e -> {
            int i = e;
            if (i == 3) {
                throw new IOException("i=" + i);
            }
        });
    }

}

Guess you like

Origin blog.csdn.net/qq_27246521/article/details/131434859