Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid using try...catch blocks

Tags:

java

try-catch

I understand these are necessary...of course to write proper code, but is there a design pattern that will help avoid having to repeat try...catch blocks repeatedly in a class? For instance, I wrote a particular class that throws 5 different exceptions.

public void iterateComparatorResults(ArrayList<ComparatorValue> results) throws IOException, IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException {
    Iterator<ComparatorValue> iterator = results.iterator();
    for(int i=0; i<results.size(); i++) {
        //Set data variables.
        setBeans(results.get(i).getClientBean(), results.get(i).getServerBean());
        setValues(results.get(i).getClientValue(), results.get(i).getServerValue());

        if(results.get(i).isMatch()) {
            //Data matches.
            runIteratorTrueAction();
        } else if(results.get(i).getInnerBeans() != null){
            //Value is a nested bean. Iterate again.
            ArrayList<ArrayList<ComparatorValue>> innerResults = results.get(i).getInnerBeans();
            for(int r=0; r<innerResults.size(); r++) {
                iterateComparatorResults(innerResults.get(r));
            }

        } else {
            //Data does not match.
            runIteratorFalseAction();
        }
    }
}

Everytime I reference this particular method is any other class, I have to use a try catch block that looks like this.

try {
    beanComparator.setIteratorFalseAction(falseAction);
                beanComparator.iterateComparatorResults(beanComparator.compareBeans(contact, compareContact));
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (IntrospectionException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

I am hoping there is some design pattern I can implement so I can create a separate class or something and hide all the try blocks in one place then reference that class and use the try blocks without actually having to write them. Similar to the way that other frameworks like Spring do? I just need a little direction on how to do this as I have no idea even where to begin.

like image 482
ryandlf Avatar asked Feb 06 '12 03:02

ryandlf


People also ask

When should you avoid try catch?

Try-catch is best used in parts of your code when you think mistakes will occur that are out of your control for whatever reason. 2. When Should You Avoid Using Try-Catch? If you know an error is likely to happen, you shouldn't use the try-catch statement since you'd rather debug the problem than disguise it.

Why you should avoid try catch?

One reason to avoid #1 is that it poisons your ability to use exception breakpoints. Normal-functioning code will never purposefully trigger a null pointer exception. Thus, it makes sense to set your debugger to stop every time one happens. In the case of #1, you'll probably get such exceptions routinely.

How do you deal with a try catch 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.


1 Answers

I'm not sure how real-world your example is, but there's no need to a) catch each exception separately, if you don't handle them differently, or b) catch them at all, in many cases.

What you're doing in your example, just printing a stack trace, is a bad idea in almost all cases. You're printing messy information to a place where no one's likely paying attention.

I follow two general guidelines:

  1. Handle the exception at the point at which it's thrown, if you can (to close an open file on a file access exception, for instance, or retry a troublesome interface (stupid unreliable bespoke USB devices...)).
  2. Allow the exception to bubble up to a point higher in your stack, where you can catch all exceptions you can't otherwise handle. Log them, display them, or kill your application, whatever makes the most sense.

I'll illustrate the second point with some code, stolen from inspired by the Java tutorials.

private String readFirstLineFromFile(String path) throws IOException
{
    try (BufferedReader br = new BufferedReader(new FileReader(path)))
    {
        return br.readLine();
    }
}

Here, we've defined a method that attempts to read from a file. Lots of things can go wrong here, but there's nothing the code at this level is going to do about that. Instead, it's going to pass the buck to the method that called it, with the throws clause. That calling method may handle the exception itself, or pass the buck to its caller, with the same clause:

private String readAllTheFiles() throws IOException
{
    for (...)
    {
        readFirstLineFromFile(...);
    }
}

Now, there's lots of debate around why Java requires the throws in this case. Many other languages don't use them, for better or worse. You'll often see RuntimeExceptions - exceptions that don't require a throws clause. If your method might throw an exception that extends from RuntimeException, you don't need to declare that fact in a throws.

like image 54
Michael Petrotta Avatar answered Sep 27 '22 22:09

Michael Petrotta