Problem with "Scopes" of Variables in Try Catch Blocks in Java

Why does a Try/Catch block create new variable scope?

Why are Objects created within the try/catch block not in scope with the rest of the method?

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:

SomeObject someObject = null;
try
{
someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); // This is fine -- unless the SomeObject
// constructor threw the exception, in which
// case someObject will be null

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:

SomeObject someObject = new SomeObject();
try
{
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod();

Re your comment:

I guess I'm confused as to why another scope has even been created for a try/catch block.

In Java, all blocks create scope. The body of an if, the body of an else, of a while, etc. — they all create a new, nested variable scope:

if (foo) {
SomeObject bar = new SomeObject();
}
bar.doSomething(); // <== Compilation error, `bar` is not defined

(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 or while. In the above if, bar may or may not have been declared (depending on the value of foo), which makes no sense because of course the compiler has no concept of the runtime value of foo. 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.)

Problem with scopes of variables in try catch blocks in Java

Because it's declared in the try block. Local variables are declared in one block are inaccessible in other blocks except if contained in it, i.e., the variables go out of scope when their block ends. Do this:

private void loadCommands(String fileName) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(fileName));

while (br.ready()) {
actionList.add(CommandFactory.GetCommandFromText(this, br.readLine()));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) try { br.close(); } catch (IOException logOrIgnore) {}
}
}

Why aren't variables declared in try in scope in catch or finally?

Two things:

  1. Generally, Java has just 2 levels of scope: global and function. But, try/catch is an exception (no pun intended). When an exception is thrown and the exception object gets a variable assigned to it, that object variable is only available within the "catch" section and is destroyed as soon as the catch completes.

  2. (and more importantly). You can't know where in the try block the exception was thrown. It may have been before your variable was declared. Therefore it is impossible to say what variables will be available for the catch/finally clause. Consider the following case, where scoping is as you suggested:


    try
    {
    throw new ArgumentException("some operation that throws an exception");
    string s = "blah";
    }
    catch (e as ArgumentException)
    {
    Console.Out.WriteLine(s);
    }

This clearly is a problem - when you reach the exception handler, s will not have been declared. Given that catches are meant to handle exceptional circumstances and finallys must execute, being safe and declaring this a problem at compile time is far better than at runtime.

Try catch block variable out of scope

isn't declaration without initialization equivalent to initialization
to null?

Local variables need to be initialized by the programmer only, where as instance variables of the class will be initialized by JVM with their default values (based on the type) during object creation.

The other way which gets rid off "out of scope error" is when I put
"return;" at the end of catch blocks.. shouldn't the code just run
fine with out it?

There are two possibilities here:

(1) Green path scenario: If there is no FileNotFoundException in the first try block, then fis variable would have been initialized successfully, so there will not be any error.

(2) Red path scenario: fis will not be initialized upon the FileNotFoundException in the first try block, so if you return from the first catch block itself, then there is no need of fis variable in the last try block (because those lines will never be executed because you are returning from the middle), so there is no initialization error.

When i take the declarations out of the method and make them static it
also works.. do you know what is the reason for this distinction?

static variables will be initialized with default values (like instance variables) by the JVM, so there will not be any variable initialization errors if you mark them as static (JVM already did initialize them).

variable scope inside the try block when accessing from the finally block?

You need to declare your variables before you enter your try block, so that they remain in scope for the rest of your method:

public static void main() throws FileNotFoundException {
File src = null;
File des = null;
try {
src = new File("src.txt");
des = new File("des.txt");
/*code*/
} finally {
/*closing code*/
if (src != null) {
System.out.print("After closing files:Size of src.txt:" + src.length() + " Bytes\t");
}
if (des != null) {
System.out.println("Size of des.txt:" + des.length() + " Bytes");
}
}
}

Variable in Try-Catch Not Available to Other Try-Catch Block?

Variables declared in try-catch blocks are local to those blocks. So, declare the variable outside the try-catch, then assign it values in the try-catch.

Problem with "scopes" of variables in try catch blocks in Java

What is the scope of a variable defined inside java try block? Why it is not accessible outside of the try block?

Any {} block defines a scope in Java. So any variable (such as y) declared inside the try block is only accessible inside the try block.

x is declared in the outer block that contains your try block (that's the block of your entire main method), so it's accessible inside your try block.

Why can't I access variables inside a try/catch block?

You have to bring them outside, because otherwise the variable exists only within the try block. But this is an improvement. If you change your code to this:

Reader reader = new FileReader("/my/file/location");
try {
//Read the file and do stuff
} catch(IOException e) {
e.printStackTrace();
} finally {
reader.close();
}

then the code in the try-block, including the finally, can all rely on the reader having been created successfully. Otherwise, in your example, if the instantiation fails your code still tries to close the reader, which will still be null, on the way out.

In this changed example the exception thrown by the instantiation of the reader doesn't get handled by the catch block.

A combination of problems led you here, one is you're more worried about trying to squash all the exceptions with one catch block than you are about making sure the reader is in a valid state before you start calling methods on it. (You'll see this one-try-block-to-rule-them-all style a lot in JDBC code where people just can't bear to write all the nested try blocks, it's too ugly to tolerate.) Also, it's very toy-example-ish to catch all the exceptions locally like this, in real life if something goes wrong you want to let the exception be thrown so the rest of the application can know something went wrong, giving you something like

public void doStuffWithFile() throws IOException {
Reader reader = new FileReader("/my/file/location");
try {
//Read the file and do stuff
} finally {
try {
reader.close();
} catch (IOException e) {
// handle the exception so it doesn't mask
// anything thrown within the try-block
log.warn("file close failed", e);
}
}
}

which is very similar to what try-with-resources does. try-with-resources creates the objects first, then executes the try block, then closes the things it created, making sure that any exception thrown on close does not mask an exception thrown in the try-block. Creating the objects still has the potential to throw an exception, it doesn't get handled by the try-with-resources.

public void doStuffWithFile() throws IOException {
try (Reader reader = new FileReader("/my/file/location")) {
//Read the file and do stuff
}
}

Variable scope in try catch block

You can just declare userInput variable outside the try-catch block:

package contactmanager;

import java.util.InputMismatchException;
import java.util.Scanner;

public class UserInterface {

public static Integer GetInput() {
Scanner in = new Scanner(System.in);
System.out.println("Welcome to the contact manager\nMake a selection below:");
System.out.println("1)Display Contacts\n2)Add new business contact\n3)Add new personal contact\n4)Quit");
Integer userInput = null;
try {
userInput = in.nextInt();
if (userInput < 1 || userInput > 4) {
System.out.println("Please enter a valid selection");
UserInterface.GetInput();
}

} catch (InputMismatchException e) {
e.getMessage();
System.out.println("Please enter a valid selection");
UserInterface.GetInput();
}

return userInput;

}

}

Issues in scope of variables while using try-catch in Java

Since Java 7 you can combine the try-catch as follows:

    FileInputStream fin = null;
try {
fin = new FileInputStream(pdfDoc);
byte fileContent[] = new byte[(int) pdfDoc.length()];
fin.read(fileContent);
} catch (IOException | FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}

Which, in my opinion, makes the code cleaner and variable scopes more obvious.



Related Topics



Leave a reply



Submit