Ali Khan
Ali Khan

Reputation: 59

Exception handling in Java Programs

This is my program structure:

main function -> call Class A obj -> Class A calls Class B obj

when it comes to exception handling, I want to exit the program with error code if exception is encountered either in main, class A or class B.

Currently, I am doing what I feel is a cumbersome process (and likely a foolish way):

-> Have exception handling within the functions of Class A and Class B.

-> Have the function exit with a value deemed 'error' (such as specific value or boolean false) if exception occurred in function.

-> main has its own try/catch but also for each function call of class A and class B, if it return is 'error', it throws exception and then exits with error code.

My contention with this approach is (a) I am throwing and handling exception potentially multiple times (at the class level and then at main level). (b) If a function in class is suppose to return a value, than I have to set aside a specific value that when received, should be interpreted as error.

any cleaner suggestions? This is for programs which will be compiled to run as executable JAR from command line and won't be a micro service (or web server based -- for those, I reckon, instead of exiting the program, you would report the error in log and continue on).

Upvotes: 0

Views: 392

Answers (5)

gidds
gidds

Reputation: 18577

Generally speaking, it's only worth catching and re-throwing an exception if:

  • you're going to throw a different type of exception (one that better fits the abstraction the method is providing, often wrapping the original exception), and/or
  • you want some side-effect (e.g. logging the error somewhere, or some clean-up that doesn't fit in a finally { } block).

If you're not doing any of those, then go for the easy way out and don't catch the exception.  But do mention it in the method's JavaDoc, even if it's unchecked.

And as others have said, returning a dedicated error code is rarely a good idea in Java; they're wordy, easy to forget, and don't propagate to the caller.  And returning a special value (e.g. null) in place of a normal return value is even worse!  Exceptions are the standard way, and that's what everyone will be expecting.

Upvotes: 1

ControlAltDel
ControlAltDel

Reputation: 35011

The thing about Exceptions in Java is that they do a lot of different things, semantically

  1. Errors in code: Exceptions like NullPointerException or SQLExceptions where your SQL isn't right. These (IMO) shouldn't be caught, or should be rethrown as Errors and caught in the uncaughtExceptionHandler (which you can define in Thread)

  2. User errors: Exceptions like NumberFormatException and exceptions on bad form data, where the user has entered invalid values. This (IMO) should be handled in place with a message near where they should correct the value

  3. Normal, expected exceptions: Exceptions like IOException / SocketException. InterruptedException is in this family too. These Exceptions are your friends(!), as they unlock the threads that are waiting on something that they should be waiting on anymore. They are part of the normal cycle of connecting to IO resources. So if a socket closes, you could log the exception somewhere (sometimes even that isn't necessary), and possibly ask the user if they want to reopen the connection.

Upvotes: 1

Roland Illig
Roland Illig

Reputation: 41625

The basic idea you should follow is to have a main method like this:

public static void main(String... args) {
    try {
        new A().run();
    } catch (ExitProgramException e) {
        System.exit(e.getCode());
    }
}

There is no predefined ExitProgramException yet. This is good, since otherwise some other class could already throw it. In this case though, you want to define all the places where this exception can be thrown. The exception class should be defined as follows:

public final class ExitProgramException extends RuntimeException {

    private final int code;

    public ExitProgramException(int code) { this.code = code; }

    public int getCode() { return code; }
}

Now, in classes A and B, you can throw new ExitProgramException(1), and everything will work as intended.

Because of the extends RuntimeException, the intermediate code does not have to know about this exception and will happily let it bubble through, from class B over class A back into the main method, where it is finally caught and converted into the exit code.

Upvotes: 1

noiaverbale
noiaverbale

Reputation: 1678

IMHO either use exceptions or error code as return value and be consistent with that approach.

In kotlin you can use powerful libraries as Arrow-kt which offers you some sofisticated types to handle errors like Try or Either to handle respectively exceptions and error codes or states.

Disclaimer: I am not affiliated with Arrow team

Upvotes: 0

Mick
Mick

Reputation: 973

Return values should NOT be used for signaling errors to the caller. In JAVA you would just throw an exception.This is a core feature.

What you are actually interested in is how to signal an error state to the command line. So, for class A and class B, use standard exception throwing. However, within the main method you might exit abnormally for some exceptions or maybe even all exceptions. Please check How exactly works the Java application exit code of the main() method? for more details.

Upvotes: 0

Related Questions