Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does everything after my try statement have to be encompassed in that try statement to access variables within it?

I'm learning java and one thing I've found that I don't like, is generally when I have code like this:

import java.util.*;
import java.io.*;

public class GraphProblem
{
    public static void main(String[] args)
    {
        if (args.length < 2)
        {
            System.out.println("Error: Please specify a graph file!");
            return;
        }


        FileReader in = new FileReader(args[1]);
        Scanner input = new Scanner(in);

        int size = input.nextInt();
        WeightedGraph graph = new WeightedGraph(size);

        for(int i = 0; i < size; i++)
        {
            graph.setLabel(i,Character.toString((char)('A' + i)));
        }

        for(int i = 0; i < size; i++)
        {
            for(int j = 0; j < size; j++)
            {
                graph.addEdge(i, j, input.nextInt());
            }
        }

        // .. lots more code

    }
}

I have an uncaught exception around my FileReader.

So, I have to wrap it in a try-catch to catch that specific exception. My question is does that try { } have to encompass everything after that in my method that wants to use either my FileReader (in) or my Scanner (input)?

If I don't wrap the whole remainder of the program in that try statement, then anything outside of it can't access the in/input because it may of not been initialized or has been initialized outside of its scope. So I can't isolate the try-catch to just say the portion that intializes the FileReader and close the try statement immediately after that.

So, is it the "best practice" to have the try statement wrapping all portions of the code that are going to access variables initialized in it?

Thanks!

like image 764
Mithrax Avatar asked Apr 30 '10 16:04

Mithrax


People also ask

Is it compulsory to add an except statement with a try statement?

Nope, not at all. Its not mandatory to put catch after try block, unless and until the try block is followed by a finally block.

What kind of statements are put inside the try block?

Place any code statements that might raise or throw an exception in a try block, and place statements used to handle the exception or exceptions in one or more catch blocks below the try block. Each catch block includes the exception type and can contain additional statements needed to handle that exception type.

Which keywords are required with a try statement?

A try statement provides the main body of code that will be invoked, and must be followed by either a catch statement, a finally statement, or both.

Are statement in try block always executed?

It always executes, regardless of whether an exception was thrown or caught. You can nest one or more try statements. If an inner try statement does not have a catch -block, the enclosing try statement's catch -block is used instead. You can also use the try statement to handle JavaScript exceptions.


2 Answers

If you are comfortable with not wrapping the code after the FileReader constructor, you can declare the FileReader outside of the try/catch block, like this:

FileReader fr = null;
try
{
    fr = new FileReader(args[1]);
}
catch (IOException e)
{
    // handle
}
// code that uses fr

This is a reasonable design, and I use it often. Make sure you properly handle, in the following code, the possibility that fr is null (i.e. the constructor threw an exception).

like image 116
Michael Petrotta Avatar answered Oct 06 '22 00:10

Michael Petrotta


This is not an issue with try/catch blocks as such. The issue is variable scoping and that you must have a try/catch block because of the checked exception and thus establish a new scope.

You also have another option - declare the checked exception(s) as throws from your method.

public static void main(String[] args) throws IOException {
    // ...code here...
}

This is perfectly legal for a main method.

If you do want to handle the exception, as you ought to in a larger program. You can define a specific try/catch around the problem block of code and use the variable outside of the scope by declare the variable outside of that scope as many have answered:

FileReader fr = null; // must be initialized here if the exception handling code 
                      // does not exit the method
try {
    fr = new FileReader(fileName);
} catch (IOException ex) {
    // log, print, and/or return
    // if you return or exit here then subsequent code can assume that fr is valid
}

You can also put the move the code to another method that deals with the exception:

private static FileReader openReader(String fileName) {
    try {
        return new FileReader(fileName);
    } catch (IOException ex) {
        // log/print exception
        return null; // caller must then expect a null
        // or
        throw new RuntimeException(...); // throw a RuntimeException of some kind (may not be good practice either)
    }
}

You could also move the file processing code to another method. This may be better and allow you to more correctly follow the open/close in finally idiom:

FileReader fr = null;
try {
    fr = new FileReader(fileName);
    Scanner input = new Scanner(fr);

    processInput(input);
} catch (IOException ex) {
    // log/print exception
} finally {
    if (fr != null) {
        try {
            fr.close();
        } catch (IOException ex) {
            // empty
        }
    }
}

private static void processInput(Scanner in) throws IOException {
    // ...processing here
}

For the close part, you could use a third party library (Apache File Utils) or write a simple method to provide a static safe close method that doesn't throw exceptions.

You really should look at breaking up large methods into smaller units and this will often provide you with a much clearer way of handling the exceptions as well.

like image 31
Kevin Brock Avatar answered Oct 06 '22 00:10

Kevin Brock