我长期以来一直批评Java中的编译器检查异常机制。 无论您是爱还是恨,都可以肯定一件事:在某些情况下,您不想与他们打交道。 Java中的解决方案是将一个检查过的异常包装在new RuntimeException(e)但这可以提供较长的堆栈跟踪,而无需添加有用的信息。 有时,我们只想告诉编译器冷静。

事实证明,通过对Java泛型的类型擦除错误功能的某些不当使用,这是有可能的。 看到这一点对于理解Java的内部运作方式具有指导意义。 我们走吧!

这是我们想要的:

public static void main(String[] args) {businessLogic();}private static void businessLogic() {List<String> configuration = readConfigurationFile();System.out.println(configuration.get(0));}private static List<String> readConfigurationFile() {try {return Files.readAllLines(Paths.get("non", "existing", "file"));} catch (IOException e) {throw softenException(e);}}

注意, businessLogic()既不捕获IOException也不声明它throws IOException 。 相反, softenException()方法将删除异常的检查。 运行它时,我们得到以下堆栈跟踪:

Exception in thread "main" java.nio.file.NoSuchFileException: non\existing\fileat sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230)at java.nio.file.Files.newByteChannel(Files.java:361)at java.nio.file.Files.newByteChannel(Files.java:407)at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)at java.nio.file.Files.newInputStream(Files.java:152)at java.nio.file.Files.newBufferedReader(Files.java:2784)at java.nio.file.Files.readAllLines(Files.java:3202)at java.nio.file.Files.readAllLines(Files.java:3242)at insanejava.SoftenExceptionsDemo.readConfigurationFile(SoftenExceptionsDemo.java:21)at insanejava.SoftenExceptionsDemo.businessLogic(SoftenExceptionsDemo.java:15)at insanejava.SoftenExceptionsDemo.main(SoftenExceptionsDemo.java:11)

! 在main方法中引发的异常是NoSuchFileException ,它是IOException的子类–已检查的异常! 怎么可能? 为什么程序中的任何方法都不必声明throws IOException

这是窍门:

private static RuntimeException softenException(Exception e) {return checkednessRemover(e);}private static <T extends Exception> T checkednessRemover(Exception e) throws T {throw (T) e;}

checkednessRemover方法使用了一个技巧,可以揭示有关Java内部工作的一些信息。 首先,将通用类型参数T绑定到RuntimeException ,以实现softenException 。 这意味着表达式throws T变成throws RuntimeException ,编译器将其解释为好像没有抛出异常。

但是语句throw (T)e; 理论上应该评估为throw (RuntimeException)e; 。 由于e是NoSuchFileException ,因此您希望此语句导致ClassCastException 。 但是,泛型在Java中的工作方式是,编译器会删除类型信息。 因此,字节码改为throw (Exception)e; ,这很好。

因此,这个奇怪的把戏表明,Java编译器从编译的代码中删除了通用信息,并且检查的异常纯粹是编译器的功能。 没有检查异常的运行时验证。

我会建议在生产代码中使用此技巧吗? 我不知道。 这很奇怪,可能没什么用,但是当我感到邪恶时,我会自己使用它。 如果没有别的,我希望学习可以让您对Java的内部运作有一些见解。

免责声明 :(1)我在其他地方读到了这个技巧,但是我再也找不到源了。 我以为这是Heinz Kabutz的出色Java 时事通讯,但我找不到源。 (2)这在 Lombok项目中 也实现为@SneakyThrows 。 如果您使用的是Lombok,则在任何情况下都不应重新实现此博客中的技巧。 请改用@SneakyThrows

翻译自: https://www.javacodegeeks.com/2018/05/a-wicked-java-trick-to-make-the-jvm-forget-to-check-exceptions.html

邪恶的Java技巧使JVM忘记检查异常相关推荐

  1. java 抛异常 jvm_邪恶的Java技巧使JVM忘记检查异常

    java 抛异常 jvm 我长期以来一直在批评Java中编译器检查异常的机制. 无论您是爱还是恨,都可以肯定一件事:在某些情况下,您不想与他们打交道. Java中的解决方案是将一个检查后的异常包装在n ...

  2. Java基础知识第二讲:Java开发手册/JVM/集合框架/异常体系/Java反射/语法知识/Java IO

    Java基础知识第二讲(Java编程规范/JVM/集合框架/异常体系/Java反射/语法知识/Java IO/码出高效) 分享在java学习及工作中,常使用的一些基础知识,本文从JVM出发,讲解了JV ...

  3. Java基础之《受检查异常和不受检查异常》

    1.最近重温了<java编程思想(第四版)>的异常章节. Java中的异常分为受检查的异常和不受检查的异常. (1)受检查的异常:这种在编译时被强制检查的异常称为"受检查的异常& ...

  4. java string rt_如何使jvm加载我的java.lang.String而不是rt.jar中的那个

    我认真研究了Java类加载器.现在,我想编写一个与rt.jar中的类之一具有相同的包名称和类名称的类.例如,我自己编写一个java.lang.String类,以及如何打破父级委托模型以使jvm加载我的 ...

  5. 利用 Java dump 进行 JVM 故障诊断

    引言 对于大型 java 应用程序来说,再精细的测试都难以堵住所有的漏洞,即便我们在测试阶段进行了大量卓有成效的工作,很多问题还是会在生产环境下暴露出来,并且很难在测试环境中进行重现.JVM 能够记录 ...

  6. java jvm调优_(第1部分,共3部分):有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的摘要...

    java jvm调优 我已经花了几个月的时间考虑审查有关性能调优,JVM,Java中的GC,Mechanical Sympathy等主题的文章和视频的缓存,并最终花了点时间–也许这就是重点我什么时候才 ...

  7. (第1部分,共3部分):有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的摘要...

    我已经花了几个月的时间考虑审查有关性能调优,JVM,Java中的GC,Mechanical Sympathy等主题的文章和视频的缓存,并最终花了点时间–也许这就是重点我什么时候需要做我的智力进步! 感 ...

  8. Java虚拟机(JVM)面试题(2022年总结最全面的面试题!!!)

    大家好啊,我是小于哥,Java虚拟无论是在年前面试还是在年后的金三银四面试都是必问的,比如: Java1.8和1.7内存模型有什么差距? 堆栈的区别是什么? 深拷贝和浅拷贝 Java会存在内存泄漏吗? ...

  9. Java虚拟机(JVM)面试题(总结最全面的面试题!!!)

    Java内存模型 我们开发人员编写的Java代码是怎么让电脑认识的 首先先了解电脑是二进制的系统,他只认识 01010101 比如我们经常要编写 HelloWord.java 电脑是怎么认识运行的 H ...

最新文章

  1. 平衡树 - treap
  2. zabbix如何监控WEB应用性能
  3. 限制输入字符串的长度
  4. 十进制大数的加法运算
  5. zabbix 监控使用宏自动发现网卡并进行监控
  6. html基础标签 1211
  7. Activity生命周期方法的调用顺序project与測试日志
  8. Oracle的回收站和闪回查询机制(二)
  9. 在LoadRunner中设置HTTP请求time-out的时间
  10. 【面试感悟】一名3年工作经验的程序员应该具备的技能
  11. FPGA_四选一数据选择器
  12. 期权策略基准指数简介
  13. ​机器如何“猜你喜欢”?深度学习模型在1688的应用实践...
  14. Distributional RL with Quantile Regression论文翻译
  15. A53开发板命令操作wifi-wap主要命令
  16. 基于Netty的聊天系统(三)协议定制----消息篇
  17. 现货黄金投资的鳄鱼法则
  18. java 输出大于n的质数_Java 计算并打印第n个质数
  19. 国际化复数形式的支持与pygettext的补丁
  20. MT6739 Android Q 驱动整理

热门文章

  1. 28、jdbc操作数据库(5)
  2. JavaFX其他事件
  3. Java虚拟机必学之四大知识要点,附学习资料
  4. Oracle入门(十三A)之Select
  5. Mysql的安装与远程登录
  6. 01)自学JavaScript
  7. javaSE视频教程正式启动
  8. 使用JDBCTemplate实现与Spring结合,方法公用
  9. 当当网新用户注册界面——界面源码
  10. html点击弹出iframe,JavaScript:关于跨iframe弹窗