When & how should constructors enforce limits on instance variables?

386 Views Asked by At

I'm new to programming and am learning Java as my first oo language, by working through Introduction to Programming Using Java by David J. Eck and reading forum posts when stuck.

My question could be considered a follow-up to Java Class Constructor Parameters with range limits which deals with limiting int arguments to an Hour class' constructor to 0 through 23.

The answers to the above question mentioned throwing either Instantiation Exception or IllegalArgumentException, but were unclear about which is better style.

Also, when, if ever, is the overhead associated with the validation code justified?

3

There are 3 best solutions below

0
On BEST ANSWER

It is correct only to throw an IllegalArgumentException.

Thrown to indicate that a method has been passed an illegal or inappropriate argument.

An InstantiationException is for a different purpose.

Thrown when an application tries to create an instance of a class using the newInstance method in class Class, but the specified class object cannot be instantiated. The instantiation can fail for a variety of reasons including but not limited to:

  • the class object represents an abstract class, an interface, an array class, a primitive type, or void

  • the class has no nullary constructor

An InstantiationException has to do with a reflection call failing to call a constructor, but an IllegalArgumentException means that the constructor (or method) was called successfully, but the block of code determined that an argument was inappropriate.

It is always best to have a little overhead to validate the arguments coming in to your constructor (and method). A program or class that isn't working properly is worse than a program that works properly and might be negligibly slower.

0
On

About the overhead

I think there isn't a rule, but I think, in general, enforcing such a thing in the constructor would make sense if your object needs an external parameter to make sense, just like the java.awt.Color object as @TNT told in the comments.

It could also make sense if you have some stateful object that can only be created using the parameters provided by the constructor, no other setters for the same parameters.

About the Exception

I can't do a better job than @rgettman did ;-) his answer makes complete sense to me

0
On

Generally, I like to be certain that an object passed into my code will be valid. If the class itself already enforces that, I can have that certainty without having to check again. Based on that, I'd say it's a good idea to carefully validate your constructor arguments and enforce your invariants at least if your class and the constructor are public, or accessible by a large body of code.

If you have a small package and a class that is only ever used within that limited context, or even a private inner class, it's ok to be more relaxed about validation.

I'd use an IllegalArgumentException or something derived from that for validation, because that type makes it clearer what happened and that the fault is with the caller.