Java 8 Java 8 lambda捕获异常

Java 8 Java 8 lambda捕获异常,java-8,unchecked-exception,Java 8,Unchecked Exception,Cay Horstmann的《不耐烦的人的爪哇8》一书中: 你不是一直都很讨厌你要处理的事情吗 Runnable中的异常?编写一个方法取消选中,以捕获所有 检查异常并将其转换为未检查的异常。对于 例如 new Thread(uncheck( () -> { System.out.println("Zzz"); Thread.sleep(1000); })).start(); // Look, no catch (InterruptedException)! 提示:定义一个接口Runnab

Cay Horstmann的《不耐烦的人的爪哇8》一书中:

你不是一直都很讨厌你要处理的事情吗 Runnable中的异常?编写一个方法
取消选中
,以捕获所有 检查异常并将其转换为未检查的异常。对于 例如

new Thread(uncheck(
() -> { System.out.println("Zzz"); Thread.sleep(1000); })).start();
// Look, no catch (InterruptedException)!
提示:定义一个接口
RunnableEx
,其
run
方法可以抛出任何 例外情况。然后实施

public static Runnable uncheck(RunnableEx runner)
在uncheck函数中使用lambda表达式

我的代码如下:

public interface RunnableEx {
    void run() throws Exception;
}

public class TestUncheck {
    public static Runnable uncheck(RunnableEx r) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    r.run();
                } catch (Exception e) {
                }
            }
        };
    }

    public static void main(String[] args) {
        new Thread(uncheck(
                () -> {
                    System.out.println("Zzz");
                    Thread.sleep(1000);
                }
        )).start();
    }
}
我是按照暗示做的吗?有更好的方法吗

还有一个补充问题:

为什么不能使用
Callable
而不是
RunnableEx?


这种从lambdas捕获异常的方法工作得很好,并且(添加了一些内容)是在流行的Java库中的
Unchecked
类中实现的

要进行比较,请参阅它们的静态方法,该方法与您的解决方案相同,只是它们的
异常处理程序和lambda省略了返回值

关于从Java 8到不耐烦者的赋值,您的
uncheck
方法不使用lambda(为此,请参阅
Unchecked.runnable
方法),并且不会引发未检查的异常。为此,您的
catch
块(当前为空)需要将异常包装为未检查的异常。有很多方法可以做到这一点,很多问题都与此相关:

  • 但一个简单的方法是:

    throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
    

    最后,为了回答
    Callable
    问题,我假设您的意思是“而不是
    Runnable
    ”?如果是这样,那是因为中的构造函数将
    Runnable
    作为参数。

    您的代码无法将选中的异常包装为未选中的异常。此外,它不遵循使用lambda表达式的提示。更正后的版本为:

    public static Runnable uncheck(RunnableEx r) {
        return () -> {
            try {
                r.run();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
    
    确实有可能进一步改进这一点。由于
    RunnableEx
    接口的全部目的是包装
    Runnable
    ,因此可以将工厂方法放在接口本身中:

    public interface RunnableEx {
        void run() throws Exception;
        public static Runnable uncheck(RunnableEx r) {
            return () -> {
                try {
                    r.run();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            };
        }
    }
    
    当然,现在您的呼叫代码必须适应:

    public static void main(String[] args) {
        new Thread(RunnableEx.uncheck(
                () -> {
                    System.out.println("Zzz");
                    Thread.sleep(1000);
                }
        )).start();
    }
    
    现在,接口本身可以实现包装功能,与
    Runnable
    兼容,这将消除使用
    Runnable
    RunnableEx
    实例来表示单个操作的需要:

    public interface RunnableEx extends Runnable {
        void runWithException() throws Exception;
        @Override default void run() {
                try {
                    runWithException();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
        }
        public static Runnable uncheck(RunnableEx r) {
            return r;
        }
    }
    
    请注意,虽然调用代码在语法上没有改变,但它首先会隐式地创建一个
    runnablex
    实例,当创建
    RunnableEx
    实例时,这就是为什么
    取消选中
    成为不可操作的原因,仅作为应创建
    RunnableEx
    而不是
    Runnable
    的标记。使用此接口定义,您可以通过

    public static void main(String[] args) {
        new Thread( (RunnableEx) () -> {
                System.out.println("Zzz");
                Thread.sleep(1000);
            }
        ).start();
    }
    

    这里不能“仅使用”一个可调用的
    Callable
    的原因是
    Callable
    仍然是一个
    Callable
    ,需要实现代码返回一个值。换句话说,没有从
    void
    void
    的隐式转换。因此可以使用它,但是lambda表达式需要
    返回null语句结尾处(
    null
    是唯一与
    Void
    兼容的值)

    公共类测试取消选中{
    publicstaticrunnable取消选中(callabler){
    返回()->{
    试试{r.call();}
    catch(异常e){抛出新的RuntimeException(e);}
    };
    }
    公共静态void main(字符串[]args){
    新线程(取消选中(
    () -> {
    System.out.println(“Zzz”);
    睡眠(1000);
    返回null;
    }
    )).start();
    }
    }
    
    public class TestUncheck {
        public static Runnable uncheck(Callable<Void> r) {
            return () -> {
                try { r.call(); }
                catch (Exception e) { throw new RuntimeException(e); }
            };
        }
    
        public static void main(String[] args) {
            new Thread(uncheck(
                    () -> {
                        System.out.println("Zzz");
                        Thread.sleep(1000);
                        return null;
                    }
            )).start();
        }
    }