Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle exceptions that occur when instantiating a class object

Tags:

java

java version "1.7.0_45"

Hello

I am initializing the class methods in the constructor. However, the new URL(uploadUrl) will throw an exception in the constructor. So if this happens the user shouldn't be able to continue. As the constructor cannot return anything, I am wondering that is the best way to handle this?

Many thanks for any suggestions,

public class MultipleFileTransfer {
    private static final String TAG = MultipartUtility.class.getSimpleName();

    private DataOutputStream dataOutputStream;
    private FileInputStream fileInputStream;
    private HttpURLConnection httpURLConnection;
    private URL url;

    public MultipleFileTransfer(final String uploadUrl) {
        dataOutputStream = null;
        fileInputStream = null;
        httpURLConnection = null;

        try {
            url = new URL(uploadUrl);
        } catch (MalformedURLException e) {
            Log.wtf(TAG, e.getMessage()); /* <-- How to handle a failure */
        }
    }

    /* Factory method that initializes the class methods and returns the class object */
    public static MultipleFileTransfer getInstance(final String uploadUrl) {

        /* Check that a valid url has been entered correctly */
        if(!URLUtil.isValidUrl(uploadUrl)) {
            Log.wtf(TAG, "Invalid url: " + uploadUrl);
            return null;
        }

        return new MultipleFileTransfer(uploadUrl);
    }
}
like image 816
ant2009 Avatar asked Jul 07 '15 05:07

ant2009


2 Answers

As the constructor cannot return anything, I am wondering that is the best way to handle this?

Typically, allow the exception to propagate to the caller, either directly or by wrapping it in your own higher-level abstraction exception. (In your case, just allowing it directly looks more appropriate.)

public MultipleFileTransfer(final String uploadUrl) throws MalformedURLException {
// -------------------------------------------------^
    dataOutputStream = null;
    fileInputStream = null;
    httpURLConnection = null;

    url = new URL(uploadUrl);
}

Since your instance isn't useful without the URL, it makes sense for construction to fail.

Or if you want to log it in the constructor (but if it's propagating, typically any logging if appropriate would be handled by the caller):

// Logging and re-throwing, but probably not recommended
public MultipleFileTransfer(final String uploadUrl) throws MalformedURLException {
// -------------------------------------------------^
    dataOutputStream = null;
    fileInputStream = null;
    httpURLConnection = null;

    try {
        url = new URL(uploadUrl);
    } catch (MalformedURLException e) {
        Log.wtf(TAG, e.getMessage());
        throw e;                       // <== Rethrowing
    }
}
like image 187
T.J. Crowder Avatar answered Nov 17 '22 10:11

T.J. Crowder


I can think of two decent ways to handle the situation:

(1) Let the constructor throw an exception. Either rethrow the same exception after logging, or throw a different exception. If the exception it throws isn't a RuntimeException (and MalformedURLException is not a RuntimeException), you'll need to add a throws clause to the constructor.

(2) Let the constructor create an object anyway, but mark it as an "invalid" object that cannot be used. I'd add an isValid() or isInvalid() method so that the caller can query whether it's valid. Other methods should throw IllegalStateException if they're called on an invalid object.

I don't think one is clearly better than the other. It depends on preference and perhaps on the design of the rest of the program.

like image 21
ajb Avatar answered Nov 17 '22 10:11

ajb