Let's say I have a class with multiple constructors, one of which is a copy-constructor (to copy an object):
public class Rectangle {
int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle source) {
this(source.width, source.height);
}
}
Is there any way I can make check if source
is null
in the copy-constructor and throw an IllegalArgumentException
if it is? Because the other constructor call has to be the first statement in my constructor.
You can do this:
public Rectangle(Rectangle source) {
this(checkNotNull(source, "Source cannot be null").width, source.height);
}
private static <T> T checkNotNull(T t, String msg) {
if (t == null) throw new IllegalArgumentException(msg);
return t;
}
I also agree with Jon Skeet that a NullPointerException
is not a bad bevahiour in this case. The only thing is that in long lines when you get an NPE it can be a bit hard to identify which object is null
, which is why a more specific message can be useful.
You can also not reinvent the wheel and use standard java.util.Objects
methods if you don't bother throwing a NullPointerException
instead:
public Rectangle(Rectangle source) {
this(Objects.requireNonNull(source, "Source cannot be null").width, source.height);
}
if your error message is expensive to build, you can provide a Supplier<String>
instead, to pay the cost of the construction of the message only when it's actually needed:
public Rectangle(Rectangle source) {
this(Objects.requireNonNull(source, () -> explainError(source)).width, source.height);
}
Yes, you can use a helper method which will throw the exception if necessary, and return the original value otherwise... you can call that within your constructor invocation, as you're allow method calls as part of argument evaluation.
// In a helper class
public static <T> T checkNotNull(T value) {
if (value == null) {
throw new IllegalArgumentException();
}
return value;
}
Then use it as:
public Rectangle(Rectangle source) {
this(Helper.checkNotNull(source).width, source.height);
}
However... I believe that NullPointerException
is the recommended exception to throw here anyway (in Effective Java 2nd edition, for example), which your existing code will throw already. So you quite possibly don't want to make any change to your existing code.
If you want a helper method for checks like this but are happy for it to throw NullPointerException
, I'd recommend using Guava and its Preconditions class, which has this and a lot of other helpful checking methods.
Also note that Java 1.7 introduced java.util.Objects
which has requireNonNull
, so you don't even need a third party library.
One text-book trick is move the initialization out of the constructor to a method. Then, you can have whatever code you want before it:
public class Rectangle {
int width, height;
public Rectangle(int width, int height) {
init(width, height);
}
public Rectangle(Rectangle source) {
if (source == null) {
throw new IllegalArgumentException("source can't be null!");
}
init(source.width, source.height);
}
private void init(int width, int height) {
this.width = width;
this.height = height;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With