JDK8中关于lambdas的bug| 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)


场景模拟


代码如下


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


运行


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


网络异常,图片无法展示
|


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


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


网络异常,图片无法展示
|


网络异常,图片无法展示
|


JDK8bug?


后面在 Stack Overflow 上发现这个


Throw RuntimeException inside Stream with Optional.orElseThrow


网络异常,图片无法展示
|


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


如下:


网络异常,图片无法展示
|


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


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


网络异常,图片无法展示
|


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


解决办法


从源码入手先~


下面是 OptionalorElseThrow源码


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


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


网络异常,图片无法展示
|


结果程序正常运行啦


网络异常,图片无法展示
|


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


还有来自 StackOverflow 的解答,


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


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


网络异常,图片无法展示
|


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


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

网络异常,图片无法展示
|


泛型


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


泛型的特点:


  1. 编译擦除


  1. 类型安全


  1. 消除强制类型转换


泛型类


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 推导泛型的类型时出错了 ,手动指定该类型即可解决问题!


  1. 可以通过升级 JDK 的版本来解决这个问题


  1. 如果你想更深入了解这个 lambda ,可以研究下


java.lang.invoke.LambdaMetafactory



目录
相关文章
|
15天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
本系列教程笔记详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。若需快速学习Kotlin,建议查看“简洁”系列教程。本期重点介绍了Kotlin与Java的共存方式,包括属性、单例对象、默认参数方法、包方法、扩展方法以及内部类和成员的互操作性。通过这些内容,帮助你在项目中更好地结合使用这两种语言。
29 1
|
16天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
26 2
|
5天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
5天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
5天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
13天前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
14 0
[Java]静态代理与动态代理(基于JDK1.8)
|
15天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
本系列教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文档重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android library开发建议以及在Kotlin和Java之间互相调用的方法。
13 1
|
15天前
|
安全 Java 编译器
Kotlin语法笔记(27) -Kotlin 与 Java 共存(二)
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。若需快速入门,建议查阅“简洁”系列教程。本文重点探讨Kotlin与Java共存的高级话题,包括属性访问、空安全、泛型处理、同步机制及SAM转换等,助你在项目中逐步引入Kotlin。
14 1
|
16天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
Kotlin语法笔记(28) -Kotlin 与 Java 混编
19 2
|
22天前
|
Java 数据库连接 编译器
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”