【问题标题】:Manually opening a Java 7 auto-managed resource手动打开 Java 7 自动管理的资源
【发布时间】:2013-04-24 21:04:42
【问题描述】:

因此,Java 7 有一个漂亮的功能,可以自动关闭 AutoCloseable 类。如果我有Bar 实现Closeable(进而扩展AutoCloseable),并且有办法从Foo 获得一个开放的Bar,我可以这样做:

try(Bar bar=foo.openBar())
  //do something
}

...和bar 将自动关闭,就像它被放在finally 子句中一样。可爱。

但是如果我想获得Bar 并稍后打开它怎么办?因为可能Bar 就像File 并且仅仅标识一个资源;我可能想识别其中很多,但只在必要时打开它们。

Bar bar=foo.getBar();
try(bar.open())  //doesn't work
  //do something
}

但是 Java 7 自动管理的方法需要我在 try 子句中分配一个变量,不是吗?

所以也许我可以很聪明,让Bar.open() 返回this(即Bar 实例),这样我就可以做到这一点:

try(Bar bar=foo.getBar().open())
  //do something
}

这可以按我的意愿运行,但它会警告我中间 Bar 实例永远不会关闭。

所以也许我可以这样做:

Bar bar=foo.getBar();
try(Bar temp=bar.open())
  //do something
}

这也是我想要的功能,但除了丑陋之外,我仍然收到警告 --- 这一次第一个 bar 变量永远不会关闭。

所以也许我可以将bar.open() 调用放在受保护的块中,如下所示:

try(Bar bar=foo.getBar())
  bar.open();
  //do something
}

这将按我想要的方式工作——大多数时候。但是如果bar.open() 抛出异常怎么办? Java 7 将尝试关闭bar,在我的实现中,它会抛出IllegalStateException,因为您无法关闭从未打开过的东西。所以它应该,对吧?因为如果有人试图在 Bar 实例打开之前关闭它,就会出现问题,我们需要一种快速失败的方法,而不是让问题在未知时间传播和浮出水面。

但也许我真的想使用自动资源管理,所以我考虑放松一下Bar.close(),这样你就可以随时关闭它,即使你还没有打开@987654349 @。但现在看看我在做什么:我正在更改我的 API(可以说让它变得低劣)只是为了使用一些语法编译器糖!!

还有其他想法吗?我想使用 Java 7 自动资源管理,以便 Java 7 会自动关闭我的资源,但想决定何时打开它,这可能不一定是在我获取的那一刻 资源。

【问题讨论】:

    标签: java java-7 resource-management


    【解决方案1】:

    一个想法

    让它关闭两次然后这样做:

    try (Bar bar=foo.getBar()) {
      try(bar=bar.open()) {
        //do something
      }
    }
    

    这仍然很丑陋,您必须编写一些代码才能使糖起作用。

    另一个想法

    或者只有两个班级。一个保存状态信息,直到您想要打开它。然后是您从第一个创建的另一个,它确实打开了。 (有点像FileFileInputStream。)

    BarInfo barInfo = foo.getBarInfo();
    ...
    try (Bar bar = barInfo.open()) {
       // do stuff with it
    }
    

    【讨论】:

    • 第一个几乎否定了句法糖——也许我们可以称之为句法苦涩! :) 但是第二个选项很有趣;我会考虑更多...
    【解决方案2】:

    啊,我有!我将在 API 中有两种不同的方法!一个是Foo.getBar(),它只返回一个Bar 实例。第二个是Foo.openBar(),这只是一个方便的方法,首先调用Foo.getBar(),然后调用Bar.open(),如下所示:

    public Bar openBar() {
      Bar bar=getBar();
      bar.open();
      return bar;
    }
    

    这样,可以通过调用Foo.openBar()来使用自动资源管理:

    try(Bar bar=foo.openBar()) {
      //do something
    }
    

    当你想简单地获得一个Bar 实例以供以后使用时,可以调用Foo.getBar()。不幸的是,如果您等到稍后再打开它,这仍然不允许您进行自动资源管理,但也许这种方法将满足一个常见的用例,同时仍然允许灵活性。

    【讨论】:

      猜你喜欢
      • 2011-11-18
      • 1970-01-01
      • 2012-03-04
      • 2012-06-25
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多