JDK8中关于lambdas的bug| Java Debug 笔记

本文正在参加「Java主题月 – Java Debug笔记活动」,详情查看 活动链接

本期4ye又带来一个奇怪的Bug啦,是关于 jdk8 中 lambdas 推导泛型失败而导致的编译期错误,下面让我们一起来看看叭 ?

Error:(24, 29) java: 未报告的异常错误java.lang.Throwable; 必须对其进行捕获或声明以便抛出

下面让我们一起来看看叭

场景模拟

代码如下

import java.util.Optional;

public class B {
    public static void main(String[] args) {
        String s=null;
        Optional.ofNullable(s).orElseThrow(() -> {
            throw new RuntimeException("");
        });
    }

}
复制代码

运行

IDEA 运行的时候,会直接抛出该错误,编译不通过

image-20210513090401425

网上搜索一番后,看到有人在说是编译器的原因,说 Eclipse 不会 (真的吗。。)

于是我半信半疑地手动编译试下,结果也不行。。

image-20210513090253668

img

JDK8bug?

后面在 Stack Overflow 上发现这个

Throw RuntimeException inside Stream with Optional.orElseThrow

image-20210513141619907

这个老哥说这个是 JDK 的 bug ,小伙伴们可以点击下面的连接去看看 ?

This is a compiler bug JDK-8047338 which prevent correct generic exception type inference. It was partially resolved in 1.8.0_92 release

如下:

image-20210513141645391

于是我看了下本地的 JDK 版本 ,都 271 了.. 也不行。

我索性将 JDK 切换成 11 的版本,结果正常编译运行起来了!

image-20210513135534687

那么问题来啦,在不升级 JDK 的情况下,怎么保证代码的正常运行呢?

解决办法

从源码入手先~

下面是 OptionalorElseThrow 源码

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { 
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}
复制代码

可以发现这是一个泛型方法,那么根据错误信息提示,尝试着手动添加上这个泛型异常~

image-20210513144912352

结果程序正常运行啦

image-20210513144944548

这里4ye还找到一个大佬在说这个bug,详情请看
zhuanlan.zhihu.com/p/111643471

还有来自 StackOverflow 的解答,

Java 8 generics + exceptions compile time error when using a lambda expression

可以发现这里的做法也是手动添加这个异常信息~

image.png

有兴趣的小伙伴们记得看一下~

完结,撒花✿✿ヽ(°▽°)ノ✿

img

泛型

最后简单复习下泛型的几种写法~ ,别忘了泛型的特点

泛型的特点:

  1. 编译擦除
  2. 类型安全
  3. 消除强制类型转换

泛型类

class Fruit<T> {}

泛型接口

interface IAnimal<T>{}

泛型变量

T a;

泛型方法

T getAnimal();

通配符

List<?>

泛型上下限原则:PECS(Producer Extends Consumer Super)

泛型上限

? extend T 属于 Producer Extends ,可以 获取值 ,但是不能修改值 。

​ 如: List<? extend T> 就表明了只能调用 get 方法,不能使用 add 方法

泛型下限

? super T 属于 Consumer Super ,可以 修改值 ,但是不能获取值 。

​ 如: List<? super T> 就表明了只能调用 add 方法,不能使用 get 方法

总结:

  1. JDK8 在使用 lambdas 推导泛型的类型时出错了 ,手动指定该类型即可解决问题!
  2. 可以通过升级 JDK 的版本来解决这个问题
  3. 如果你想更深入了解这个 lambda ,可以研究下 java.lang.invoke.LambdaMetafactory

我是4ye,我们下期再见啦,ヾ( ̄▽ ̄)ByeBye

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享