java 抛异常 jvm_邪恶的Java技巧使JVM忘记检查异常
java 拋異常 jvm
我長(zhǎng)期以來(lái)一直在批評(píng)Java中編譯器檢查異常的機(jī)制。 無(wú)論您是愛(ài)還是恨,都可以肯定一件事:在某些情況下,您不想與他們打交道。 Java中的解決方案是將一個(gè)檢查后的異常包裝在new RuntimeException(e)但這可以提供較長(zhǎng)的堆棧跟蹤,而無(wú)需添加有用的信息。 有時(shí),我們只想告訴編譯器冷靜。
事實(shí)證明,通過(guò)對(duì)Java泛型的類(lèi)型擦除錯(cuò)誤功能的某些不當(dāng)使用,這是有可能的。 實(shí)際操作對(duì)理解Java的內(nèi)部運(yùn)作方式具有指導(dǎo)意義。 我們走吧!
這是我們想要的:
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()方法將刪除異常的檢查。 運(yùn)行它時(shí),我們得到以下堆棧跟蹤:
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方法中引發(fā)的異常是NoSuchFileException ,它是IOException的子類(lèi)–已檢查的異常! 怎么可能? 為什么程序中的任何方法都不必聲明throws IOException ?
這是竅門(mén):
private static RuntimeException softenException(Exception e) {return checkednessRemover(e);}private static <T extends Exception> T checkednessRemover(Exception e) throws T {throw (T) e;}checkednessRemover方法使用了一個(gè)技巧,可以揭示有關(guān)Java內(nèi)部工作的一些信息。 首先,將通用類(lèi)型參數(shù)T綁定到RuntimeException ,以實(shí)現(xiàn)softenException 。 這意味著表達(dá)式throws T變成throws RuntimeException ,編譯器將其解釋為好像沒(méi)有拋出異常。
但是語(yǔ)句throw (T)e; 理論上應(yīng)該評(píng)估為throw (RuntimeException)e; 。 由于e是NoSuchFileException ,因此您希望此語(yǔ)句導(dǎo)致ClassCastException 。 但是,泛型在Java中的工作方式是,編譯器會(huì)刪除類(lèi)型信息。 因此,字節(jié)碼改為throw (Exception)e; ,這很好。
因此,這個(gè)奇怪的技巧表明Java編譯器從編譯的代碼中刪除了通用信息,而檢查的異常純粹是編譯器的功能。 沒(méi)有檢查異常的運(yùn)行時(shí)驗(yàn)證。
我會(huì)建議在生產(chǎn)代碼中使用此技巧嗎? 我不知道。 這很奇怪,可能沒(méi)什么用,但是當(dāng)我感到邪惡時(shí),我會(huì)自己使用它。 如果沒(méi)有別的,我希望學(xué)習(xí)可以讓您對(duì)Java的內(nèi)部運(yùn)作有一些見(jiàn)解。
免責(zé)聲明 :(1)我在其他地方讀到了這個(gè)技巧,但是我再也找不到源了。 我以為這是Heinz Kabutz出色的Java專(zhuān)家 通訊,但我找不到源。 (2)這在 Lombok項(xiàng)目中 也實(shí)現(xiàn)為@SneakyThrows 。 如果您使用的是Lombok,則在任何情況下都不應(yīng)重新實(shí)現(xiàn)此博客中的技巧。 請(qǐng)改用@SneakyThrows 。
翻譯自: https://www.javacodegeeks.com/2018/05/a-wicked-java-trick-to-make-the-jvm-forget-to-check-exceptions.html
java 拋異常 jvm
總結(jié)
以上是生活随笔為你收集整理的java 抛异常 jvm_邪恶的Java技巧使JVM忘记检查异常的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 房间怎么画 房间简笔画教程
- 下一篇: java项目教训_[免费电子书]分析超过