Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it okay to throw exceptions from the constructor in this case? [closed]

While working on a course (as in, school courses) database system for a school project, I stumbled upon an issue of debate.

I have a class called Course. Here is a constructor (the other one is a blank constructor that assigns default values) for the class:

public Course(String name, String code, char level, int academicYear)
{
    serialNumber = nextSerialNumber++;
    if (name == null) 
    {
        throw new NullPointerException("Name can not be null.");
    }
    else
    {
        this.name = name;
    }  
    if (code == null)
    {
        throw new NullPointerException("Code can not be null.");
    }
    else
    {
        this.code = code;
    }
    if (indexOf(level, VALID_LEVEL) == -1)
    {
        throw new InvalidLevelException("Level must be one of " 
            + "characters defined in the public array in Course.");
    }
    else
    {
        this.level = level;
    }
    if (String.valueOf(academicYear).length() != NUMBER_OF_DIGITS_IN_YEAR)
    {
        throw new InvalidYearException("Year must be a four digit number!");
    }
    else
    {
        this.academicYear = academicYear;
    }
}

Where

InvalidLevelException

and

InvalidYearException

are custom exceptions that are subclasses of

RuntimeException

I throw exceptions from that constructor to indicate if anything has gone wrong. For example, if, while reading from the data file, I encounter bad data, I can reject it and write it to a log (as the project mandates), simply by putting that constructor in a try-catch block and then catching those exceptions, and inside that catch block, log the bad data.

After showing this code to my teacher, he said it is inappropriate to throw exceptions from the constructor. However, I have read numerous Stackoverflow posts in which this practice is encouraged.

My question is: Is it okay to throw exceptions from the above constructor?

Reputable sources (for example, official documents or authoritative books) attached with an answer would be greatly appreciated.

Thanks very much in advance.

like image 956
user3666617 Avatar asked May 22 '14 21:05

user3666617


People also ask

Is it safe to throw an exception from a constructor?

The short answer to the question “can a constructor throw an exception in Java” is yes! Of course, properly implementing exceptions in your constructors is essential to getting the best results and optimizing your code.

In which case is it necessary to have constructors which throw exceptions?

A constructor should throw an exception when it is unable to complete the construction of said object.

Is it OK to throw exception in constructor in C++?

If your construction fails and throws an exception, ~Mutex() will not be called and mutex_ will not be cleaned up. Don't throw exceptions in constructors.

Is it bad to throw exceptions?

You should always be as precise as possible when defining contracts. Saying throws Exception is therefore a bad idea. It's bad for the same reason it is bad practice to say a method returns an Object when it is guaranteed to return a String .


2 Answers

I don't see anything wrong from throw an exception in the constructor. It means that the object can't be created in a valid state.

Personally you throw the right exception, but don't use custom exceptions if you can use Java exceptions InvalidLevelException and InvalidYearException should be replaced with IllegalArgumentException while NullPointerException is the right exception if an argument is null.

Another thing i would change is the style: Check your arguments then do everything else.

public Course(String name, String code, char level, int academicYear)
{
    if (name == null) {
        throw new NullPointerException("Name can not be null.");
    }
    if (code == null) {
        throw new NullPointerException("Code can not be null.");
    }

    if (indexOf(level, VALID_LEVEL) == -1) {
        throw new InvalidLevelException("Level must be one of " 
            + "characters defined in the public array in Course.");
    }

    if (String.valueOf(academicYear).length() != NUMBER_OF_DIGITS_IN_YEAR) {
        throw new InvalidYearException("Year must be a four digit number!");
    }

    serialNumber = nextSerialNumber++;
    this.code = code;
    this.academicYear = academicYear;
    this.level = level;
    this.name = name;
}

(p.s if the object can't be created, why increment serial number?)

It's very elegant right? -- Another thing is to make the messages more specific.

Anyway, i think the best source is the entire JDK platform since it's a common pattern to thrown an exception in the constructor.


As Luiggi Mendoza said in comments, it's HashMap constructor if you need a prof for your teacher

187     public More ...HashMap(int initialCapacity, float loadFactor) {
188         if (initialCapacity < 0)
189             throw new IllegalArgumentException("Illegal initial capacity: " +
190                                                initialCapacity);
191         if (initialCapacity > MAXIMUM_CAPACITY)
192             initialCapacity = MAXIMUM_CAPACITY;
193         if (loadFactor <= 0 || Float.isNaN(loadFactor))
194             throw new IllegalArgumentException("Illegal load factor: " +
195                                                loadFactor);
196 
197         // Find a power of 2 >= initialCapacity
198         int capacity = 1;
199         while (capacity < initialCapacity)
200             capacity <<= 1;
201 
202         this.loadFactor = loadFactor;
203         threshold = (int)(capacity * loadFactor);
204         table = new Entry[capacity];
205         init();
206     }
like image 172
Marco Acierno Avatar answered Oct 14 '22 01:10

Marco Acierno


Is it okay to throw exceptions from the above constructor?

Your question touches on one aspect of Exception handling. The other aspect is accurately describing the problem. I'll go through both briefly.

Is the exception thrown where the code fails?

The reasoning for this is simple. You want the user to know exactly where the problem occurred, and if you're propagating your exception all over the place, then you're going to make it more difficult for a user of your code to decipher where the issue is. If the issue is in the constructor of an object, you know the issue occurred during that object's creation.

That provides the user with an important clue, which is all you can do. You don't know how the user will mis use your code, so you need to make it as easy as possible for them to decipher the source of their issue.

Does the exception message describe the problem?

Using the appropriate type of Exception is important. If they've provided an invalid parameter, throw an IllegalArgumentException. If they have provided a null value, throw a NullPointerException. The Exception should be as effective as possible at describing the problem.

The second part of this is the message you attach. The amount of times I've seen:

Exception: Exception Occurred

is frustratingly high. It doesn't help in the slightest, and is an extremely lazy way of handling your code. You need to make it clear:

NullPointerException: Parameter X was null

Instantly, the user knows that the value they're passing for X is null. Simply put, make sure that the message specifically describes the issue that caused it.

Extra Reading

  • For more details on this subject, check out this link for the best practises on exception handling. This will help clear up any other questions you've got.
like image 3
christopher Avatar answered Oct 14 '22 01:10

christopher