22

Could anyone explain me why in the last lines, br is not recognized as variable? I've even tried putting br in the try clause, setting it as final, etc. Does this have anything to do with Java not support closures? I am 99% confident similar code would work in C#.

private void loadCommands(String fileName) {
    try {
        final BufferedReader 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) br.close(); //<-- This gives error. It doesn't
                                    // know the br variable.
    }       
}

Thanks

3
  • 3
    C# has a using keyword that, like a for loop, allows you to define a variable limited by the subsequent scope. Java does not have that. Commented May 18, 2010 at 2:00
  • Btw: I wouldn't do e.printStackTrace() here. Your program would continue to run with possibly an empty action list. You don't want to have that. Just throw through and let your application exit or stall with a clear error message so that the enduser can take action accordingly. Commented May 18, 2010 at 2:32
  • I still don't know how am I supposed to deal with Exceptions in Java. In C#, I'd let this go up in the stack, but if I want to do that, I'll have to put a throws declaration in this function and in any function that calls this one. Its a PITA. Commented May 18, 2010 at 2:47

3 Answers 3

42

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) {}
    }       
}
Sign up to request clarification or add additional context in comments.

6 Comments

I waas almost sure I tried that same code here and it didn't work. Well, thanks!
ok, great. Now it won't let me do the br.close() without surrounding it in another try catch block. What am I supposed to do?
I dunno if I'd say verbose or irritating.
That's why under each IOUtils exist.
Maybe you, devoured elysium, omitted the ` = null;` which is hard to accept, because when you omit it, you get the message 'br might be null/ not be initialized', which means, it is null, but if you write it explicitly, it is silently accepted. Too nanny-like, but well meant, imho.
|
6

To update this answer since Java 7 & 8 release:

Firstly, If you declare a variable inside a traditional try{} block you won't have access to that variable outside of that try block.

Now since Java 7 you can create a Try-With-Resources which can shorten your code written, it removes your "scope" problem and it also automatically closes resources for you!!! A Hat Trick in this situation ;)

The equivalent code with Try-With-Resources is:

private void loadCommands(String fileName) {
    try (BufferedReader 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();
    } 
}

Notice that now you don't even need to worry about the scope of the variable since there is no need to call .close() it is being automatically done for you!

Any class that implements the AutoClosable interface can be used in a Try-With-Resources block. As a quick example I'll leave this here:

public class Test implements AutoCloseable {

public static void main(String[] args) {
    try (Test t = new Test()) {
        throw new RuntimeException();
    } catch (RuntimeException e) {
        System.out.println(e);
    } catch (Exception e) {
        System.out.println(e);
    }
    System.out.println("The exception was caught and the program continues! :)");
  }

@Override
public void close() throws Exception {
    // TODO Auto-generated method stub
   }
}

If you need more explanation on using try-with-resources click here

Comments

1

br is defined in the try block so it's not in the scope in finally block.

Define br outside of the try block.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.