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

Daniel Martin
  • 23,083
  • 6
  • 50
  • 70
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • 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. – Yishai May 18 '10 at 02: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. – BalusC May 18 '10 at 02: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. – devoured elysium May 18 '10 at 02:47

3 Answers3

43

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) {}
    }       
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Artefacto
  • 96,375
  • 17
  • 202
  • 225
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

Jet_C
  • 644
  • 9
  • 12
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.

ZZ Coder
  • 74,484
  • 29
  • 137
  • 169