0

Java's AutoCloseable feature "reuses" try/catch semantics:

try (Stream x = ...) {
    // work with x
}

// x is out of scope and was auto-closed

I'm curious why they didn't introduce new semantics for this new feature. try implies that you expect the body to throw an exception at one point or another (or that it may). This seems much different to me than "instantiate this resource and close it when I'm done". That doesn't have anything to do with handling exceptions. Why not something like this...

with (Stream x = ...) { ... }

using (Stream x = ...) { ... } // I know, C# syntax

I'm not looking to fuel a debate, I want to know the reason the Java team decided to re-use try for this feature.

Josh M.
  • 26,437
  • 24
  • 119
  • 200
  • 6
    It does not reuse `try/catch` semantics, but `try/finally` semantics. – Turing85 Jun 21 '18 at 17:13
  • This is still considered as off topic, unless one of the java developers may come around and answers this very specific question – Lino Jun 21 '18 at 17:14
  • *"try implies that you expect the body to throw an exception at one point"* - no, that simply is no longer true. It is called [`try-with-resource`](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) and simply "reuses" the `try` keyword which is nice since you can handle exception in the same construct and do not have to have them nested in some way. – luk2302 Jun 21 '18 at 17:14
  • *"// I know, C# syntax"* - It's kind of ironic to lament the C# syntax in this case. All that does in C# is obscure the behind-the-scenes creation of a try/finally. And in the process overloading a keyword that's already used for something completely different (in a different context), `using`. Java is simply exposing the underlying structure a bit more and not creating or overloading unnecessary keywords. – David Jun 21 '18 at 17:22
  • `try-with-resources` is always [translated in to a `try-catch-finally` construct, even if you don't explicitly write a `catch` or `finally` yourself](https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html#jls-14.20.3.1). (If you do write a `catch` or `finally` block, [it's translated in to an outer `try` block](https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html#jls-14.20.3.2).) – Radiodef Jun 21 '18 at 17:31
  • @luk2302 It is true. The fact that the catch is optional most definitely does not imply that try-with-resources is not related to exceptions. It is. The whole reason try-with-resources exists is because Java does not have the concept of stack unwinding, and an exception occurring might leave a resource open. It does **not** have to be a **checked exception** - which means that a catch is not necessary. try-with-resources is **not** RAII. – Michael Jun 21 '18 at 17:40
  • @Michael could you elaborate the part of stack unwinding and how this affects upclosed resources? – Turing85 Jun 21 '18 at 17:42
  • @Turing In C++, for example, when an exception is thrown or a method exits, [the stack "unwinds"](https://stackoverflow.com/questions/2331316/what-is-stack-unwinding). This means that the destructors for all stack-local variables are called. The destructor of a (well-designed) resource can then close itself automatically. Because Java has a garbage collector, we can't know exactly when an object is destroyed. Thus the "destructor" concept doesn't really make sense in Java (there's `Object.finalize` but now deprecated). `finally` solves this problem. `try-with-resources` improves the syntax – Michael Jun 21 '18 at 18:28
  • @Michael ah okay, I get it. Maybe [value types of project valhalla](http://openjdk.java.net/projects/valhalla/) will bring stack unwinding =) – Turing85 Jun 21 '18 at 18:33
  • I didn't mean literally it "reuses" try/catch or try/catch/finally. I was getting more at the English meaning of the word "try" being misapplied to what is actually happening in the case of try-with-resources. – Josh M. Jun 21 '18 at 20:46

2 Answers2

3

Java always tries its best to be backwards compatible. It's the cause of pretty much all of the weird or unfortunate aspects of the language today. It's happened a handful of times, but introducing a new keyword such as with or using was not a decision to be taken lightly. If they'd introduced a new keyword using, old code such as int using = 0 would not compile against the latest version of Java*

try-with-resources was basically introduced to reduce the verbosity of the following common pattern:

SomeResource resource;
try {
    resource = new Resource();
    resource.foo();
}
//optional catch
finally {
    if (resource != null) resource.close();
}

Because try was already involved before, adding additional functionality to try was the logical happy medium.


* Interestingly, a similar discussion was had over Java 10's var, which is not actually a keyword but a 'reserved type name' (so the semantics are slightly different):

Risk: source incompatibilities (someone may have used var as a type name.)

Michael
  • 41,989
  • 11
  • 82
  • 128
2

The question is partially about a design choice in the Java language. Due to the nature of the question, this answer is only a partial answer of the question.

The try-with-resources does not reuse the try-catch concept, but the try-finally concept. Although seldom seen, try-finally has its uses. You could, for example, instead of explicitly catching an exception and re-throwing it, simply do some cleanup in the finally-block.1

The nature of AutoCloseable resources fits quite nicely in this use case: Open an AutoCloseable resource, do something and at the end close it, no matter what.

One could argue that starting this process through a try seems artificial. This, however, was a design decision of the language committe and is therefore not up to debate. If I had to guess, I would go with Michael's line of argumentation and say that they did not want to introduce a new keyword to stay backwards compatible.


1I am aware of the fact that was pointed out by @Radiodef, that a try-with-resources will be translated to a try-catch-finally. From my point of view, however, this is an implementation detail and a tool to specify the behaviour. It is not essential for understanding the semantics.

Turing85
  • 18,217
  • 7
  • 33
  • 58
  • Thanks. To me the word "try" just doesn't say "create a resource and dispose of it when I'm done". Hence the question. – Josh M. Jun 21 '18 at 20:45