Explicit Java Arguments on a Chain Constructors

Let's say I have a class with several constructors, one of which is a copy constructor (for copying 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 a way I can check if source null in the copy constructor and throw an IllegalArgumentException if that is the case? Since the other constructor calling is like the first statement in my constructor.

+7
java constructor copy-constructor
source share
5 answers

You can do it:

 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 John Skeet that NullPointerException not a bad bevahiour in this case. The only thing is that in long queues, when you get NPE, it can be a little difficult to determine which object is null , so a more specific message might be useful.

You also cannot reinvent the wheel and use the standard java.util.Objects methods unless you set 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 Supplier<String> instead to pay the cost of building the message only when it is really needed:

  public Rectangle(Rectangle source) { this(Objects.requireNonNull(source, () -> explainError(source)).width, source.height); } 
+12
source share

Yes, you can use a helper method that will throw an exception if necessary and return the original value otherwise ... you can call this in a constructor call, because you allow method calls as part of evaluating the arguments.

 // In a helper class public static <T> T checkNotNull(T value) { if (value == null) { throw new IllegalArgumentException(); } return value; } 

Then use it like:

 public Rectangle(Rectangle source) { this(Helper.checkNotNull(source).width, source.height); } 

However ... I believe that NullPointerException is the recommended exception to throw it at all (e.g. in Effective Java 2nd edition, for example), which will already use your existing code. Thus, you may not want to make any changes to your existing code.

If you need a helper method for such checks, but he is glad that he threw a NullPointerException , I would recommend using Guava and its Preconditions class, which has this and many other useful 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.

+7
source share

One trick in a text book translates initialization from a constructor to a method. Then you can get any 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; } } 
+3
source share

If you really want to throw an IllegalArgumentException , I think the cleanest solution is to use a static method instead of a constructor:

 public static Rectangle from(Rectangle source) { if (source == null) { throw new IllegalArgumentException("source can't be null!"); } return new Rectangle(source.width, source.height); } 

Or you can simply add a copy method:

 public Rectangle copy() { return new Rectangle(this.width, this.height); } 

I would prefer the latter, as it eliminates the need to worry about the fact that the Rectangle may be null. Note that this will cause NPE if you use it with a null object, which is perhaps another sign that the NPE is ok.

+2
source share

You can do it as follows:

 int width, height; public Rectangle(int width, int height) { this.width = width; this.height = height; } public Rectangle(Rectangle source) { if(source != null) { width = source.width; height = source.height; } } 
+1
source share

All Articles