JDK8中关于lambdas的bug

本期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 运行的时候,会直接抛出该错误,编译不通过

JDK8中关于lambdas的bug_第1张图片

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

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

image-20210513090253668

JDK8中关于lambdas的bug_第2张图片

JDK8bug?

后面在 Stack Overflow 上发现这个

Throw RuntimeException inside Stream with Optional.orElseThrow

JDK8中关于lambdas的bug_第3张图片

这个老哥说这个是 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

如下:

JDK8中关于lambdas的bug_第4张图片

于是我看了下本地的 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();
    }
}

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

JDK8中关于lambdas的bug_第5张图片

结果程序正常运行啦

JDK8中关于lambdas的bug_第6张图片

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

还有来自 StackOverflow 的解答,

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

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

JDK8中关于lambdas的bug_第7张图片

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

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

JDK8中关于lambdas的bug_第8张图片

泛型

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

泛型的特点:

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

泛型类

class Fruit {}

泛型接口

interface IAnimal{}

泛型变量

T a;

泛型方法

T getAnimal();

通配符

List

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

泛型上限

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

​ 如: List 就表明了只能调用 get 方法,不能使用 add 方法

泛型下限

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

​ 如: List 就表明了只能调用 add 方法,不能使用 get 方法

总结:

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

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

欢迎关注,交个朋友呀!! ( •̀ ω •́ )y

作者简介 :Java4ye ,很高兴认识你!!

公众号: Java4ye 博主滴个人公众号~ ,嘿嘿 喜欢就支持下啦

让我们开始这一场意外的相遇吧!~

欢迎留言!谢谢支持!ヾ(≧▽≦*)o

你可能感兴趣的:(java,java,jdk,bug,lambda)