java – try-with-resources中的死代码警告,但不是在翻译的try-c
下面的代码使用
Java 8中引入的
try -with-resources结构.偶然的Throw()方法被声明为抛出OccasionalException,Resource的close()方法抛出一个CloseException. Eclipse(版本:Neon Release(4.6.0),Build id:20160613-1800)在标有//死代码的行上添加一个警告,表示该分支是死代码.隐含地,Eclipse确认标有//活动代码的行不是死代码.
Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; } 我很困惑.如果偶然的Throw()抛出其OccasionalException,那么try-with-resources应该将其作为主要异常捕获,然后尝试关闭资源.如果关闭资源会抛出一个CloseException,那么它将在OccasionalException下被抑制,因此不会捕获CloseException.因此,唯一需要捕获的CloseException是在try中的块成功完成时,这意味着该值为非null.所以看起来“死代码”实际上是活着的,而“活着代码”实际上已经死了.我不确定编译器实际上应该在这里识别出什么,但至少,这里的“死代码”似乎不应该被称为死. 更复杂的是,不使用try-with-resources表单的翻译表单根本没有标记任何死代码警告. (我非常有信心,基于14.20.3.2. Extended try-with-resources,我的翻译是正确的,但如果这里有错误,我不会感到惊讶……) Object expandedTry() throws OccasionalException { Object value = null; try { Resource resource = new Resource(); Throwable $primary = null; try { occasionallyThrow(); value = new Object(); } catch (Throwable t) { $primary = t; throw t; } finally { if (resource != null) { if ($primary != null) { try { resource.close(); } catch (Throwable $suppressed) { $primary.addSuppressed($suppressed); } } else { resource.close(); } } } } catch (CloseException e) { if (value == null) { // alive (not dead!) } else { // alive } } return value; } 我是否遗漏了一些东西会使if-else中的任何一个分支死于其中一个,而不是另一个? 完整代码 这是包含辅助异常类型,Resource类和顶级类定义的完整代码. public class TestTryWithResources { /** Exception thrown by Resource's close() method */ @SuppressWarnings("serial") static class CloseException extends Exception {} /** AutoCloseable declared to throw a CloseException */ static class Resource implements AutoCloseable { @Override public void close() throws CloseException {} } /** An occasionally thrown exception */ @SuppressWarnings("serial") static class OccasionalException extends Exception {} /** Method declared to throw an occasional exception */ void occasionallyThrow() throws OccasionalException {} /* * Method using try-with-resources. Eclipse warns that the * portion marked with "// dead code" is Dead code. */ Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; } /* * Method not using try-with-resources. This is the translation * of the try-with-resources in tryWithResources,according to * [14.20.3 try-with-resources][1]. Eclipse does not warn about * any of the code being Dead code. * * [1]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3 */ Object expandedTry() throws OccasionalException { Object value = null; try { Resource resource = new Resource(); Throwable $primary = null; try { occasionallyThrow(); value = new Object(); } catch (Throwable t) { $primary = t; throw t; } finally { if (resource != null) { if ($primary != null) { try { resource.close(); } catch (Throwable $suppressed) { $primary.addSuppressed($suppressed); } } else { resource.close(); } } } } catch (CloseException e) { if (value == null) { // alive } else { // alive } } return value; } } 回应评论 Amin J’s answer建议在设置值之后使用资源来改变Eclipse的代码分析.但这不起作用.在使用资源之后,例如通过打印它,Luna和Neon中仍然存在死码警告: 解决方法
由于某种原因,静态代码分析器认为资源将在try声明之后立即关闭,而根据
this教程,资源在语句之后关闭.
try-with-resources语句确保在语句结束时关闭每个资源. 因此,例如,如果您更改代码以在值为(下面的代码)后使用资源,则它不会警告您死代码(但在Eclipse Luna上测试). Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); resource.someMethod(); // using the resource,so eclipse thinks it's not closed yet (correctly) } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; } UPDATE 这是我在设置值后使用资源(在本例中为reader)测试的实际代码. Object val = null; try (BufferedReader reader = new BufferedReader(new FileReader("C:file.txt"))) { val = new Object(); System.out.println("got here"); reader.readLine(); } catch(IOException e){ System.out.println("io ex"); if ( val == null){ } else{ } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |