异常

一:Unchecked Exception

Unchecked exception也叫做RuntimeException,出现RuntimeException通常是因为我们的代码有问题。RuntimeException是不需要被捕获的。也就是说如果有RuntimeException,没有捕获也可以通过编译。

但是后续的代码就不会再进行处理了。

List<Integer> integers = Arrays.asList(0,1,2,3,4,5);
        integers.forEach(i->{
            System.out.println(1 / i);
        });

输出:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at test.testJava.Test2.lambda$main$0(Test2.java:13)
    at java.util.Arrays$ArrayList.forEach(Arrays.java:3880)
    at test.testJava.Test2.main(Test2.java:12)

用try-catch捕获后程序可以继续进行。

List<Integer> collect = Stream.of(1, 0, 3, 4, 0, 5, 6).collect(Collectors.toList());
        collect.forEach(i -> {
            try {
                System.out.println(1 / i);
            } catch (ArithmeticException e) {
                log.info("不能为0:{}",i);
                e.printStackTrace();
            }
        });

输出:

1
18:31:57.614 [main] ERROR test.testJava.Test2 - 不能为0:0
0
0
18:31:57.627 [main] ERROR test.testJava.Test2 - 不能为0:0
0
0
java.lang.ArithmeticException: / by zero
    at test.testJava.Test2.lambda$main$0(Test2.java:21)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at test.testJava.Test2.main(Test2.java:19)
java.lang.ArithmeticException: / by zero
    at test.testJava.Test2.lambda$main$0(Test2.java:21)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at test.testJava.Test2.main(Test2.java:19)

简单但是破坏了lambda表达式的最佳实践。代码变得臃肿。

将try,catch移到一个wrapper方法中:

static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
        return i -> {
            try {
                consumer.accept(i);
            } catch (ArithmeticException e) {
                log.error("Arithmetic Exception occured : " + e.getMessage());
                System.err.println(
                        "Arithmetic Exception occured : " + e.getMessage());
            }
        };
    }

使用:

List<Integer> collect = Stream.of(1, 0, 3, 4, 0, 5, 6).collect(Collectors.toList());
collect.forEach(
lambdaWrapper(i -> {
System.out.println(1 / i);
})
);

输出:

1
18:40:44.594 [main] ERROR test.testJava.Test2 - Arithmetic Exception occured : / by zero
0
0
18:40:44.600 [main] ERROR test.testJava.Test2 - Arithmetic Exception occured : / by zero
0
0
Arithmetic Exception occured : / by zero
Arithmetic Exception occured : / by zero

但是上面的wrapper固定了捕获ArithmeticException,我们再将其改编成一个更通用的类:

static <T, E extends Exception> Consumer<T>
    consumerWrapperWithExceptionClass(Consumer<T> consumer, Class<E> clazz) {

        return i -> {
            try {
                consumer.accept(i);
            } catch (Exception ex) {
                try {
                    E exCast = clazz.cast(ex);
                    log.error("Exception occured:{},Exception的名字:{}" ,exCast.getMessage(),exCast.getClass());
                    System.err.println(
                            "Exception occured : " + exCast.getMessage());
                } catch (ClassCastException ccEx) {
                    throw ex;
                }
            }
        };
    }

使用:

List<Integer> collect = Stream.of(1, 0, 3, 4, 0, 5, 6).collect(Collectors.toList());
        collect.forEach(
                consumerWrapperWithExceptionClass(i ->{
                            System.out.println(1 / i);
                        }
                    ,ArithmeticException.class
            )
        );

输出:

1
18:49:52.890 [main] ERROR test.testJava.Test2 - Exception occured:/ by zero,Exception的名字:class java.lang.ArithmeticException
0
0
18:49:52.917 [main] ERROR test.testJava.Test2 - Exception occured:/ by zero,Exception的名字:class java.lang.ArithmeticException
0
0
Exception occured : / by zero
Exception occured : / by zero

 二:checked Exception

checked Exception是必须要处理的异常,我们还是看个例子:

static void throwIOException(Integer integer) throws IOException {
    }
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
        integers.forEach(i -> throwIOException(i));

上面我们定义了一个方法抛出IOException,这是一个checked Exception,需要被处理,所以在下面的forEach中,程序会编译失败,因为没有处理相应的异常。

static <T> Consumer<T> consumerWrapper(
            ThrowingConsumer<T, Exception> throwingConsumer) {

        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };
    }

调用:

integers.forEach(consumerWrapper(i -> throwIOException(i)));

封装异常,用来通用

static <T, E extends Exception> Consumer<T> consumerWrapperWithExceptionClass(
            ThrowingConsumer<T, E> throwingConsumer, Class<E> exceptionClass) {

        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                try {
                    E exCast = exceptionClass.cast(ex);
                    System.err.println(
                            "Exception occured : " + exCast.getMessage());
                } catch (ClassCastException ccEx) {
                    throw new RuntimeException(ex);
                }
            }
        };
    }

调用:

integers.forEach(consumerWrapperWithExceptionClass(
                i -> throwIOException(i), IOException.class));
package test.testJava;

/**
 * @FunctionalInterface   函数式接口
 *      1:接口有且仅有一个抽象方法
 *      2:允许定义静态方法
 *      3:允许定义默认方法
 *      4:允许java.lang.Object中的public方法
 *      该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。
 *      加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错
 *
 * @param <T>
 * @param <E>
 */
@FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
    void accept(T t) throws E;
}
原文地址:https://www.cnblogs.com/bulrush/p/13405762.html