Is IllegalStateException appropriate for an immutable object? - java

Would you throw an IllegalStateException if:
A method is unable to do its job because of the value(s) of one or more fields
Those fields are final and assigned only in the constructor?
Textbook example: your class is an immutable Collection<BigInteger> and your method is supposed to return the maximum element, but this instance is empty.
I have read Kevin Bourillon`s blog post on the subject and I am not sure which rule applies.
UnsupportedOperationException - this means that the method invoked will always fail for an instance of this class (concrete type), regardless of how the instance was constructed.
Definitely not. Many instances of this class are not empty and the operation would have succeeded.
IllegalStateException - ... there does exist at least one alternate state that the instance in question could have been in, which would have passed the check ... <snip> ... Note also that this exception is appropriate whether or not it is possible to actually mutate this aspect of the instance's state, or it's already too late.
Not quite. This instance was constructed with zero length, so this instance is not and could never have been non-empty.
IllegalArgumentException - throwing this exception implies that there exists at least one other value for this parameter that would have caused the check in question to pass.
Might apply if the parameter in question is the implicit this parameter. This is the exception I am tempted to throw, but I am concerned that it could be confusing.
Update: changed example from Collection<Integer> to Collection<BigInteger> because the fact that there was an identity element (Integer.MIN_VALUE) distracts from the question.

It doesn't sound like any of the common exception classes you mention above fit into the Textbook example.
You should throw a NoSuchElementException as that's exactly what the Collections.max() method does.

I think IllegalStateException is appropriate here. The instance could have been in the correct state, if it was constructed correctly (i.e. the "it's already too late" part).

If the state of the class is valid (empty collection), the max element is just null. If the state is not valid, an IllegalArgumentException should have been thrown at construction time.

IllegalStateException comes closest to what you want: "this exception is appropriate whether or not it is possible to actually mutate this aspect of the instance's state".
Not UnsupportedOperationException, since it might succeed for some instance of that class, and throwing IllegalArgumentException for a method that (presumably) takes no arguments will certainly confuse people.

Is IllegalStateException appropriate for an immutable object?
No, because immutable objects only have one state, and could not have pased from one legal state to another.
So, you're constructing an immutable object, and your object should have a max method
class YourObject {
public BigInteger max(){ ... }
}
I this case IllegalAgumentException should be the correct, but not until the method is executed, but when the object is created!
So, in this scenario, if you have an immutable collection of bigintegers, and you create it with zero elements you are receiving an "invalid argument" upon the collection creation, that's when you have to throw the exception.
I agree with Jon, if your use case, or in you analysis, you're willing to support the rest of the operations, you could throw NoSuchElementException, but I think that would be to postpone the problem. Better would be to avoid the object creation in first place.
So, throwing IllegalArgumentException would be like:
// this is my immutable object class
final class YourObject {
private final Collection<BigInteger> c;
public YourObject( BigInteger ... values ) {
if( values.length == 0 ) {
throw new IllegalAgumentException("Must specify at least one value");
}
... initialize the rest...
}
public BigInteger max() {
// find and return the max will always work
}
}
Client:
YourObject o = new YourObject(); // throws IllegalArgumentException
// the rest is not executed....
doSomething( o ) ;
...
doSomething( YourObject o ) {
BigInteger maximum = o.max();
}
In this case you don't need to check for anything in doSomething because the program would fail at the instance creation, which in turn would be fixed at development time.
Throwing NoSuchElementException would be like:
final class YourObject {
private final Collection<BigInteger> c;
public YourObject( BigInteger ... values ) {
// not validating the input :-/ oh oh..
... initialize the rest...
}
public BigInteger max() {
if( c.isEmpty() ) { throw NoSuchElementException(); }
// find and return the max will always work after this line
}
}
Client:
YourObject o = new YourObject(); // it says nothing
doSomething( o ) ;
...
doSomething( YourObject o ) {
BigInteger maximum = o.max();// ooops!, why? what?...
// your object client will start questioning what did I do wrong
// and chais of if( o != null && o.isEmpty() || moonPhaseIs... )
}
Bear in mind, that, if a program is to fail, the best thing you can do is to making it fail fast.
Collections.max have a different purpose, because being an utility method (not an immutable object ), he cannot held responsibility for the empty collection creation ( he wasn't present when that happened ), the only thing he can do is to say "There is no such a thing as max in this collection" hence NoSuchElementException.
One last remark, RuntimeExceptions, should be used for programming mistakes only ( those that can be fixed by testing the application before releasing it )

You should thrown an UnsupportedOpertationException because that's what the Java Standard Library does in the same circumstance. Your example is a type qualifier object protocol. This pattern was defined in "An Empirical Study of Object Protocols in the Wild":
Some types disable certain methods for the lifetime of
the object. In the type qualifier category, an object instance will enter an abstract state S at construction-time which it will never leave. Calls to an instance
method m, if it is disabled in state S will always fail.
In your example, your object enters an abstract state which I'll call EmptyCollection at construction time and it never leaves that state because the collection field is final. In the EmptyCollection abstract state all calls to the getMax() instance method will always fail.
Beckman studied open source Java programs looking for object protocols and categorized the resulting classes. The third most common protocol category, appearing in 16.4% of the protocols sampled, was type qualifier.
Beckman's paper lists many type qualifier examples and I selected three of them and in each case the unavailable method throws an UnsupportedOperationException:
When you create an unmodifiable list by calling Colections.unmodifiableList(...) and then call the add method on the resulting list.
When you create a java.nio.ByteBuffer that is not backed by an array and then call the array method.
When you create a java.imageio.ImageWriteParam that does not support compression and then call the setCompressionMode method.
Notice that these examples do not follow Kevin Bourillon's advice that you cite. The failure of these methods is dependent on how the instances were constructed. In examples 1 and 2 the instances that succeed and fail may be of different concrete classes since List and ByteBuffer are abstract. However, ImageWriteParam is a concrete class so one instance of ImageWriteParam may throw the UnsupportedOperationException while another one may not. Since the Java Standard Library designers also defined the exception types I would follow their lead instead of Mr. Bourillon's.
P.S. You should use IllegalStateException when instead the abstract state of your object can change at runtime. The other 83.6% of the examples in Beckman's paper are of this type.

Related

Generic type in getConstructors() in Class

In the generic class Class<T> the method getConstructors() has a return type with unknown generic type parameter instead of T. The reason for this is explainend in the javadoc.
Note that while this method returns an array of Constructor<T> objects (that is an array of constructors from this class), the return type of this method is Constructor<?>[] and not Constructor<T>[] as might be expected. This less informative return type is necessary since after being returned from this method, the array could be modified to hold Constructor objects for different classes, which would violate the type guarantees of Constructor<T>[].
A colleague of mine and I have tried to understand that explanation. In our understanding they are basically saying that it is of unknown generic type, because some caller could put other Constructor objects into that array. Did we get that right? And if so, why would someone design an API this way. Wouldn't it be better to use the specific type and trust the programmer to use the array correctly? To us it sounds a little like "We are making a worse API because the programmer using it might try something stupid". Where lies our fallacy?
The point that was mentioned by Ashu Pachauri in the comment (namely, that the array is returned for backward compatibility) is certainly valid. And in general, arrays and generics don't play together very well. (For evidence, look for all the stackoverflow questions related to "Generic Arrays"...)
Additionally, there is a rule that an API should be easy to use and hard to misuse. In this case, this is related to the Principle of least astonishment: Someone obtaining the constructors with this method could perform a perfectly legal sequence of operations on the returned array, and in the end, receive an unexpected ClassCastException. So one could say that the fact that a Constructor<?>[] array is returned aims at a "fail-fast" behavior.
An illustrative example:
import java.lang.reflect.Constructor;
public class GetConstructorsReturnType
{
public static void main(String[] args) throws Exception
{
// This causes a warning, due to the cast, but imagine
// this was possible
Constructor<DerivedA> constructorsA[] =
(Constructor<DerivedA>[])DerivedA.class.getConstructors();
// The following lines are valid due to the subtype
// relationship, but would not be valid if constructorsA
// was declared as "Constructor<?>"
Constructor<? extends Base> constructors[] = constructorsA;
constructors[0] = DerivedB.class.getConstructor();
// This causes a ClassCastException (and would also not
// be possible constructorsA was declared as "Constructor<?>"
DerivedA instance = constructorsA[0].newInstance();
}
}
class Base
{
}
class DerivedA extends Base
{
public DerivedA()
{
}
}
class DerivedB extends Base
{
public DerivedB()
{
}
}
It's the exact same reason why you are not allowed to do new Constructor<T>[], but you are allowed to do new Constructor<?>[]. You can apply your same argument and say "Wouldn't it be better to use the allow the specific type and trust the programmer to use the array correctly?" Well, Java decided no. (You can imagine that inside the getConstrucotrs method, they need to create an array of Constructor, and they cannot do new Constructor<T>[] but they can do new Constructor<?>[].)
Of course, you can make an unchecked cast of the Constructor<?>[] to the Constructor<T>[], but that will give you a warning in your code, in which case you would take responsibility for making sure it's safe. But if the getConstructors method this this unchecked cast in their code, you as the caller would never be warned about the unsafeness.

Object creation (state initialisation) and thread safety

I am look into the book "Java Concurrency in Practice" and found really hard to believe below quoted statement (But unfortunately it make sense).
http://www.informit.com/store/java-concurrency-in-practice-9780321349606
Just wanted to get clear about this 100%
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}
While it may seem that field values set in a constructor are the first
values written to those fields and therefore that there are no "older"
values to see as stale values, the Object constructor first
writes the default values to all fields before subclass
constructors run. It is therefore Possible to see the default value
for a field as a stale value
Regarding bolded statement in above,
I am aware that the behaviour BUT now it is clear that this calling hierarchy of constructors is NOT guarantee to be ATOMIC (calling super constructors in single synchronised block that is guarded by a lock), but what would be the solution? imagine a class hierarchy that has more than one level (even it is not recommended, lets assume as it is possible). The above code snippest is a kind of a prototype that we see everyday in most of the projects.
You misread the book. It explicitely says:
The problem here is not the Holder class itself, but that the Holder is not properly published.
So the above construct if fine. What's not fine is to improperly publish such an object to other threads. The book explains that in details.
When creating a new object things happen sequentially. I don't know the precise order, but it's something like: allocate the space and initialize it to zeroes, then set the fields that get constant values, then set the fields that get calculated values, then run the constructor code. And, of course, it's got to initialize the subclasses in there somewhere.
So if you try to work with an object that is still being constructed, you can see odd, invalid values in the fields. This doesn't usually happen, but ways to do it:
Reference a field that doesn't yet have a value during an assignment to another field.
Reference a value in the constructor that doesn't get assigned till later in the constructor.
Reference a field in an object in a field in an object that was just read from an ObjectInputStream. (OIS often takes a long time to put values in objects it's read.)
Before Java 5, something like:
public volatile MyClass myObject;
...
myObject = new MyClass( 10 );
could make trouble because another thread could grab the reference to myObject before the MyClass constructor was finished and it would see bad values (zero instead of 10, in this case) inside the object. With Java 5, the JVM is not allowed to make myObject non-null until the constructor is finished.
And today you can still set myObject to this within the constructor and accomplish the same thing.
If you're clever, you can also get hold of Class fields before they've been initialized.
In your code example, (n != n) would be true if something changed the value between the two reads of n. I guess the point is n starts as zero, get's set to something else by the constructor, and assertSanity is called during the construction. In this case, n is not volatile so I don't think the assert will ever be triggered. Make it volatile and it will happen once every million times or so if you time everything precisely right. In real life this kind of problem happens just often enough to wreak havoc but rarely enough that you can't reproduce it.
I guess theoretically it is possible. It is similar to double checked locking problem.
public class Test {
static Holder holder;
static void test() {
if (holder == null) {
holder = new Holder(1);
}
holder.assertSanity();
}
...
If test() is called by 2 threads, thread-2 might see the holder in a state when initialization is still in progress so n != n may happen to be true. Here is bytecode for n != n:
ALOAD 0
GETFIELD x/Holder.n : I
ALOAD 0
GETFIELD x/Holder.n : I
IF_ICMPEQ L1
as you can see JVM loads field n to operand stack twice. So it may happen that the first var gets value before init and the seccond after init
the comment:
the Object constructor first writes the default values to all fields
before subclass constructors run
seems wrong. My prior experience is that the default values for a class are set before its constructor is run. that is a super class will see its init-ed variables set before its constructor runs and does things. This was root of bug a friend looked at where a base class was calling a method during construction that the super class implemented and set a reference that was defined with initialization to null in the super class. the item would be there until entry to the constructor at which time the init set it to null value.
references to the object are not available to another thread (assuming none generated in the constructor) until it completes construction and object reference is returned.

Instance variable verification

Reading effective java, it mentions that we need to validate method parameters as a good practice, throw exceptions for public and assert for private methods. But, do we need to take any measure against instance variable.
EG: (dont take example as a use case, main question is Do I need to validate instance var or Not ?. Example was used only for explaining what i mean to ask. )
class Tree {
private Node root;
public doSomething() {
TreeNode node = root;
}
}
Now lets say root was never initialized and doSomething() was called directly, it would result in NullPtrException.
Do we need to guard against it ? If yes then how ? If no then why not ?
How about:
if (root == null) {
throw new SomethingException();
}
TreeNode node = root;
Simply put, just perform a null check on the root variable, and if it is null then execute code accordingly to fix that problem or throw a new exception for it.
The established practice to check method parameters can be generalized to check correct usage of a class. In the given example it is illegal to call method doSomething() when the instance variable root has not yet been initialized.
If you want a best practice rule, it is not to generally check instance variables, but to check that a certain usage protocol of a class is obeyed. (Unless the class is written in a way that no particular protocol needs to be followed, which is usually the better option.) This check will of course typically involve checking instance variables.
In contrast to throwing an IllegalArgumentException after a negative method parameter check, a protocol violation should lead to an IllegalStateException.
In the given example an IllegalStateException should be thrown, because that instance is not in a state where doSomething() may be called.
Move any validation code of instance variables to constructors and setters so you check it whenver it will be set or changed and throw any Exceptions if input is invalid BEFORE the change is made.
this keeps the instance variables in a valid state at all times for fully constructed objects so you don't have to sprinkle extra validation everywhere else.

is it possible to get the class of the interface <Set>

Am having some arguments say (String a, Treeset b, Set c)
and I try to get the class by arguments[i].getClass(); of the above arguments..
is Iit possible to get the class of the interface <Set>.
For example:
Class[] argumentTypes = new Class [arguments.length];
for (int i = 0 ; i < arguments.length ; i++)
{
argumentTypes[i] = arguments[i].getClass();
}
The code you've given will find the classes of the arguments (i.e. the values provided to the method) - but those can never be interfaces; they'll always be concrete implementations. (You can never pass "just a set" - always a reference to an object which is an instance of an implementation of the interface, or a null reference.)
It sounds like you want the types of the parameters - which you'd get via reflection if you absolutely had to, finding the Method and then getting the parameters from that with getParameterTypes. But given that you're within the method, you already know the parameter types, because they're at the top of the method... I'm not sure the best way of finding "the currently executing" method, if that's what you're after.
If you're just trying to get the class associated with Set, you can use Set.class of course. But again, it's not really clear what you're trying to do.
EDIT: Okay, judging from your comment, there are some logical problems with what you're trying to do. Going from the values of arguments to which method would be invoked is impossible in the general case, because you've lost information. Consider this, for example:
void foo(String x) {}
void foo(Object y) {}
foo("hello"); // Calls first method
foo((Object) "hello"); // Calls second method
Here the argument values are the same - but the expressions have a different type.
You can find all methods which would be valid for the argument values - modulo generic information lost by type erasure - using Class.isAssignableFrom. Does that help you enough?
Note that you'll also need to think carefully about how you handle null argument values, which would obviously be valid for any reference type parameter...
You can use http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getInterfaces()
You will get the class what the caller provided.
I mean,in below class you will get HashSet.
Set set=new HashSet();
System.out.println(set.getClass());
You can do this in two ways given below
Set s = new //any class that implements it for example HashSet or TreeSet etc.;
s.getClass().getName(); //This will return the name of the subclass which is refered by s.
or if in other way can do it
Set s = null;
s.getClass();//This causes NullPointer Exception

Is it good practice to make the constructor throw an exception? [duplicate]

This question already has answers here:
When to throw an exception?
(33 answers)
Closed 4 years ago.
Is it a good practice to make the constructor throw an exception?
For example I have a class Person and I have age as its only attribute. Now
I provide the class as
class Person{
int age;
Person(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
public void setAge(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
}
Throwing exceptions in a constructor is not bad practice. In fact, it is the only reasonable way for a constructor to indicate that there is a problem; e.g. that the parameters are invalid.
I also think that throwing checked exceptions can be OK1, assuming that the checked exception is 1) declared, 2) specific to the problem you are reporting, and 3) it is reasonable to expect the caller to deal with a checked exception for this2.
However explicitly declaring or throwing java.lang.Exception is almost always bad practice.
You should pick an exception class that matches the exceptional condition that has occurred. If you throw Exception it is difficult for the caller to separate this exception from any number of other possible declared and undeclared exceptions. This makes error recovery difficult, and if the caller chooses to propagate the Exception, the problem just spreads.
1 - Some people may disagree, but IMO there is no substantive difference between this case and the case of throwing exceptions in methods. The standard checked vs unchecked advice applies equally to both cases.
2 - For example, the existing FileInputStream constructors will throw FileNotFoundException if you try to open a file that does not exist. Assuming that it is reasonable for FileNotFoundException to be a checked exception3, then the constructor is the most appropriate place for that exception to be thrown. If we threw the FileNotFoundException the first time that (say) a read or write call was made, that is liable to make application logic more complicated.
3 - Given that this is one of the motivating examples for checked exceptions, if you don't accept this you are basically saying that all exceptions should be unchecked. That is not practical ... if you are going to use Java.
Someone suggested using assert for checking arguments. The problem with this is that checking of assert assertions can be turned on and off via a JVM command-line setting. Using assertions to check internal invariants is OK, but using them to implement argument checking that is specified in your javadoc is not a good idea ... because it means your method will only strictly implement the specification when assertion checking is enabled.
The second problem with assert is that if an assertion fails, then AssertionError will be thrown, and received wisdom is that it is a bad idea to attempt to catch Error and any of its subtypes.
I've always considered throwing checked exceptions in the constructor to be bad practice, or at least something that should be avoided.
The reason for this is that you cannot do this :
private SomeObject foo = new SomeObject();
Instead you must do this :
private SomeObject foo;
public MyObject() {
try {
foo = new SomeObject()
} Catch(PointlessCheckedException e) {
throw new RuntimeException("ahhg",e);
}
}
At the point when I'm constructing SomeObject I know what it's parameters are
so why should I be expected to wrap it in a try catch?
Ahh you say but if I'm constructing an object from dynamic parameters I don't know if they're valid or not.
Well, you could... validate the parameters before passing them to the constructor. That would be good practice.
And if all you're concerned about is whether the parameters are valid then you can use IllegalArgumentException.
So instead of throwing checked exceptions just do
public SomeObject(final String param) {
if (param==null) throw new NullPointerException("please stop");
if (param.length()==0) throw new IllegalArgumentException("no really, please stop");
}
Of course there are cases where it might just be reasonable to throw a checked exception
public SomeObject() {
if (todayIsWednesday) throw new YouKnowYouCannotDoThisOnAWednesday();
}
But how often is that likely?
As mentioned in another answer here, in Guideline 7-3 of the Java Secure Coding Guidelines, throwing an exception in the constructor of a non-final class opens a potential attack vector:
Guideline 7-3 / OBJECT-3: Defend against partially initialized
instances of non-final classes When a constructor in a non-final class
throws an exception, attackers can attempt to gain access to partially
initialized instances of that class. Ensure that a non-final class
remains totally unusable until its constructor completes successfully.
From JDK 6 on, construction of a subclassable class can be prevented
by throwing an exception before the Object constructor completes. To
do this, perform the checks in an expression that is evaluated in a
call to this() or super().
// non-final java.lang.ClassLoader
public abstract class ClassLoader {
protected ClassLoader() {
this(securityManagerCheck());
}
private ClassLoader(Void ignored) {
// ... continue initialization ...
}
private static Void securityManagerCheck() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
return null;
}
}
For compatibility with older releases, a potential solution involves
the use of an initialized flag. Set the flag as the last operation in
a constructor before returning successfully. All methods providing a
gateway to sensitive operations must first consult the flag before
proceeding:
public abstract class ClassLoader {
private volatile boolean initialized;
protected ClassLoader() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
// Last action of constructor.
this.initialized = true;
}
protected final Class defineClass(...) {
checkInitialized();
// regular logic follows
...
}
private void checkInitialized() {
if (!initialized) {
throw new SecurityException(
"NonFinal not initialized"
);
}
}
}
Furthermore, any security-sensitive uses of such classes should check
the state of the initialization flag. In the case of ClassLoader
construction, it should check that its parent class loader is
initialized.
Partially initialized instances of a non-final class can be accessed
via a finalizer attack. The attacker overrides the protected finalize
method in a subclass and attempts to create a new instance of that
subclass. This attempt fails (in the above example, the
SecurityManager check in ClassLoader's constructor throws a security
exception), but the attacker simply ignores any exception and waits
for the virtual machine to perform finalization on the partially
initialized object. When that occurs the malicious finalize method
implementation is invoked, giving the attacker access to this, a
reference to the object being finalized. Although the object is only
partially initialized, the attacker can still invoke methods on it,
thereby circumventing the SecurityManager check. While the initialized
flag does not prevent access to the partially initialized object, it
does prevent methods on that object from doing anything useful for the
attacker.
Use of an initialized flag, while secure, can be cumbersome. Simply
ensuring that all fields in a public non-final class contain a safe
value (such as null) until object initialization completes
successfully can represent a reasonable alternative in classes that
are not security-sensitive.
A more robust, but also more verbose, approach is to use a "pointer to
implementation" (or "pimpl"). The core of the class is moved into a
non-public class with the interface class forwarding method calls. Any
attempts to use the class before it is fully initialized will result
in a NullPointerException. This approach is also good for dealing with
clone and deserialization attacks.
public abstract class ClassLoader {
private final ClassLoaderImpl impl;
protected ClassLoader() {
this.impl = new ClassLoaderImpl();
}
protected final Class defineClass(...) {
return impl.defineClass(...);
}
}
/* pp */ class ClassLoaderImpl {
/* pp */ ClassLoaderImpl() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
}
/* pp */ Class defineClass(...) {
// regular logic follows
...
}
}
You do not need to throw a checked exception. This is a bug within the control of the program, so you want to throw an unchecked exception. Use one of the unchecked exceptions already provided by the Java language, such as IllegalArgumentException, IllegalStateException or NullPointerException.
You may also want to get rid of the setter. You've already provided a way to initiate age through the constructor. Does it need to be updated once instantiated? If not, skip the setter. A good rule, do not make things more public than necessary. Start with private or default, and secure your data with final. Now everyone knows that Person has been constructed properly, and is immutable. It can be used with confidence.
Most likely this is what you really need:
class Person {
private final int age;
Person(int age) {
if (age < 0)
throw new IllegalArgumentException("age less than zero: " + age);
this.age = age;
}
// setter removed
This is totally valid, I do it all the time. I usually use IllegalArguemntException if it is a result of parameter checking.
In this case I wouldn't suggest asserts because they are turned off in a deployment build and you always want to stop this from happening, but they are valid if your group does ALL it's testing with asserts turned on and you think the chance of missing a parameter problem at runtime is more acceptable than throwing an exception that is maybe more likely to cause a runtime crash.
Also, an assert would be more difficult for the caller to trap, this is easy.
You probably want to list it as a "throws" in your method's javadocs along with the reason so that callers aren't surprised.
I have never considered it to be a bad practice to throw an exception in the constructor. When the class is designed, you have a certain idea in mind of what the structure for that class should be. If someone else has a different idea and tries to execute that idea, then you should error accordingly, giving the user feedback on what the error is. In your case, you might consider something like
if (age < 0) throw new NegativeAgeException("The person you attempted " +
"to construct must be given a positive age.");
where NegativeAgeException is an exception class that you constructed yourself, possibly extending another exception like IndexOutOfBoundsException or something similar.
Assertions don't exactly seem to be the way to go, either, since you're not trying to discover bugs in your code. I would say terminating with an exception is absolutely the right thing to do here.
I am not for throwing Exceptions in the constructor since I am considering this as non-clean. There are several reasons for my opinion.
As Richard mentioned you cannot initialize an instance in an easy manner. Especially in tests it is really annoying to build a test-wide object only by surrounding it in a try-catch during initialization.
Constructors should be logic-free. There is no reason at all to encapsulate logic in a constructor, since you are always aiming for the Separation of Concerns and Single Responsibility Principle. Since the concern of the constructor is to "construct an object" it should not encapsulate any exception handling if following this approach.
It smells like bad design. Imho if I am forced to do exception handling in the constructor I am at first asking myself if I have any design frauds in my class. It is necessary sometimes, but then I outsource this to a builder or factory to keep the constructor as simple as possible.
So if it is necessary to do some exception handling in the constructor, why would you not outsource this logic to a Builder of Factory? It might be a few more lines of code but gives you the freedom to implement a far more robust and well suited exception handling since you can outsource the logic for the exception handling even more and are not sticked to the constructor, which will encapsulate too much logic. And the client does not need to know anything about your constructing logic if you delegate the exception handling properly.
It is bad practice to throw Exception, as that requires anyone who calls your constructor to catch Exception which is a bad practice.
It is a good idea to have a constructor (or any method) throw an exception, generally speaking IllegalArgumentException, which is unchecked, and thus the compiler doesn't force you to catch it.
You should throw checked exceptions (things that extend from Exception, but not RuntimeException) if you want the caller to catch it.

Categories