For example:
try
{
SomeObject someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //can't access someObject!
But you can declare it before the try/catch
block and then it works fine:
SomeObject someObject;
try
{
someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //works fine
I'm just wondering the design reason for this. Why are Objects created within the try/catch
block not in scope with the rest of the method? Maybe I'm not understanding deep down how a try/catch
works besides just watching for Exceptions
thrown.
In Java, any time you have a
{ }
pair, you can create a new scope.Consider the following
The try/catch just follows this idiom, and enforces a
{ }
pair to be created.To respond to your followup of a non-bracketed if statement, consider:
results in
However, this will compile just fine.
Why this is so, according to the JLS Chapter 14, section 9, if is defined as:
And Statement is defined as (14.5)
So a block, expression statement, or empty statement those are just fine. But a declaration (defined in chapter 6) is not in the grammar of statement.
They are. Variables declared within the
try/catch
block are not in scope in the containing block, for the same reason that all other variable declarations are local to the scope in which they occur: That's how the specification defines it. :-) (More below, including a reply to your comment.)Here's an object created within a
try/catch
which is accessible outside of it:Note the difference. Where the variable is declared defines the scope in which it exists, not where the object was created.
But based on the method names and such above, the more useful structure for that would be:
Re your comment:
In Java, all blocks create scope. The body of an
if
, the body of anelse
, of awhile
, etc. — they all create a new, nested variable scope:(In fact, even a block without any control structure creates one.)
And if you think about it, it makes sense: Some blocks are conditional, like the one defining the body of an
if
orwhile
. In the aboveif
,bar
may or may not have been declared (depending on the value offoo
), which makes no sense because of course the compiler has no concept of the runtime value offoo
. So probably for consistency, the designers of Java went with having all blocks create a new nested scope. (The designer of JavaScript went the other way — there is no block scope at all, yet, though it's being added — and that approach also confuses people.)try/catch
creates a new scope for the simple reason that it is a block level element. In fact, simply placing{}
just randomly inside a method will create a new block of code with it's own local scope.The scope of a variable or object is in the scope (defined by curly braces {}) in which it is defined.
Since try catch initiates a new scope where some error can be thrown so the objects defined inside try catch are not available outside it's scope.
Every time you do use a bracket '{' you're expressing a new scope in both C++ and Java. You're attempt to try an operation requires some internal setup and scoping the names allows for quick jumps back out of the try block without a lot of cleanup.
Some languages will let you access those scoped variables outside of the scope as long as there isn't a name conflict (like in Python), but this requires an slightly different internal stack structure and could still increase the costs of the try catch regardless.
Also it's just how scope definitions are defined in Java -- as many of the other answers pointed out.