标签:java eclipse try-with-resources
下面的代码使用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{
}
}
标签:java,eclipse,try-with-resources 来源: https://codeday.me/bug/20190711/1429763.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。