Flow control with try catch to reduce redundancy I've seen a similar question to this but mine's a little more specific. I have the below

File f = new File("./data.txt");
if(f.isFile())
{
    try
    {
        FileChannel fc = new RandomAccessFile(f,"r").getChannel();
        //Get information and return it
    }
    catch(FileNotFoundException e)
    {
        System.out.println("FileNoFoundException: "+e.getMessage());
    }
}
else
{
    //If the file wasn't found, return default values
}


I was wondering, should I just put the default returning of the information in the catch block? I assumed that'd be a no because you're not really supposed to use it to control flow. But having the both the if and the try catch just looks too redundant to me.
In cases like this, I like taking a default-unless-better approach... Consider this re-working of your code to do the same thing in a different order.

The basic premise is:


set up a default value (or null if it is a complicated thing to do).
do the hard work which may be missing dependencies or may fail
if the hard work completes successfully, return that result.


The reason this works well is because you can exit from the hard work at any point, and have the default standing by to continue.....

... also, as an exercise, use the try-with-resources and new NIO2 features in Java7

// set up the default value...
SomeValue result = null;
Path path = Paths.get("./data.txt");
if (Files.isRegularFile(path)) {
    try (SeekableByteChannel channel =
            Files.newByteChannel(path, StandardOpenOptions.READ)) {

        // do the work required for your file....
        ...

        // after everything is successful... set the result:
        result = new SomeValue(....real arguments ....);
    } catch (IOException ioe) {
        System.out.println("FileNoFoundException: " + e.getMessage());
    }
}
result == null ? new SomeValue(defaults...) : result;


Additionally, there is no reason, if you are in a method that builds these things, that you can't return immediately with the right answer.

Often if you are doing things like the above, it indicates that what you are doing should be in a sub-method, with an early-return when you have a successful setup, and a default return value when things fail.