2

So Java 7 has a nifty feature that automatically closes an AutoCloseable class. If I have Bar implement Closeable (which in turn extends AutoCloseable), and have a way to get an open Bar from a Foo, I can do this:

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

...and bar will automatically be closed, just as if it were put in a finally clause. Lovely.

But what if I want to get a Bar and open it later? Because maybe a Bar is like a File and merely identifies a resource; I may want to identify a lot of them, but only open them when necessary.

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

But the Java 7 auto-managed approach requires me to assign a variable in the try clause, no?

So maybe I can be clever and have Bar.open() return this (i.e. the Bar instance), so that I can do this:

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

This functions as I want, but it gives me a warning that the intermediate Bar instance is never closed.

So maybe I can do this:

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

This too functions the way I want, but besides being ugly as heck, I still get a warning---this time that the first bar variable is never closed.

So maybe I can put the bar.open() call inside the protected block, like this:

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

That will work the way I want---most of the time. But what if bar.open() throws an exception? Java 7 will try to close bar, which, in my implementation, will throw an IllegalStateException because you can't close something that has never been opened. And so it should, right? Because if someone tries to close a Bar instance before it has been opened, something is screwy, and we want a fail-fast approach instead of letting the problem propagate and surface at an unknown time.

But maybe I really want to use auto-resource management, and so I consider relaxing Bar.close() so that you can close it at any time, even if you haven't opened the Bar. But now look what I'm doing: I'm changing my API (arguably making it inferior) just to use some syntactic compiler sugar!!

Any other ideas? I want to use Java 7 auto-resource management so that Java 7 will close my resource automatically, but I want to decide when to open it, which may not necessarily be at the moment I acquire the resource.

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272

2 Answers2

1

One idea

What about letting it be closed twice and do this:

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

That's still pretty ugly and you do have to write some code to make the sugar work.

Another idea

Or just have two classes. One that holds the state information until you want to open it. Then there is another one that you create from the first and it really does open. (Sort of like a File and an FileInputStream.)

BarInfo barInfo = foo.getBarInfo();
...
try (Bar bar = barInfo.open()) {
   // do stuff with it
}
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
  • 1
    The first pretty much negates the syntactic sugar---maybe we could call it _syntactic bitter_! :) But the second option is interesting; I'll think more on it... – Garret Wilson Apr 30 '13 at 20:41
0

Ah, I have it! I'll have two distinct methods in the API! One will be Foo.getBar() which simply returns a Bar instance. The second will be Foo.openBar(), which is just a convenience method that first calls Foo.getBar() and then calls Bar.open() like this:

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

This way, one can use auto-resource-management by calling Foo.openBar():

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

When one wants to simply get a Bar instance to be used later, one can call Foo.getBar(). Unfortunately this still doesn't allow you to do auto-resource-management if you wait until later to open it, but maybe this approach will satisfy a common use case while still allowing flexibility.

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272