1

I know that if I have an overloaded method in Java that can accept a parameter of several different types, and I want to pass null to the method, I need to explicitly cast it to one of the accepted types. My question is, is it possible to choose which version of the method is called on null from within the method itself (e.g. by adding another overload to handle the null)?

My problem is the following - I have a class with an overloaded constructor that accepts one parameter:

public class MyClass {

    public MyClass(A arg) {
        // do something
    }

    public MyClass(B arg) {
        // do something else
    }
}

The use case is such that if the class is constructed with a null, then only the second version of the constructor makes sense. But having to do new MyClass((B)null) every time is error-prone. If I accidentally use the cast to A, then the wrong constructor gets executed. And I also cannot introduce the following check in my A constructor:

if (arg == null) {
    this((B)arg);
}

because this(...) is not the first statement. Of course, I can duplicate the code from the B constructor inside this check, or introduce another method to do what the B constructor does and then call it from both inside the constructor and inside this check, but this doesn't seem like a "clean" solution (and may not always be possible, e.g. in the case of cascading constructors).

Is there a way for me to only have to do new MyClass(null) and have the B version of the constructor executed every time?

I tried to add this overload, but the compiler complained:

public MyClass(null arg) {
    this((B)arg);
}
Artyom
  • 1,599
  • 12
  • 22

2 Answers2

4

But having to do new MyClass((B) null) every time is error-prone.

If you are going to use bare constructors like that, that is the best mechanism that the Java language has to offer.

But you could avoid this by replacing the new calls with static object factory methods; e.g.

  public static MyClass newANull() {
      return new MyClass((A) null);
  }

  public static MyClass newBNull() {
      return new MyClass((B) null);
  }

(Obviously, you would need better names for the methods ...)


Note that using a factory method also allows you to do things like return the same "ANull" or "BNull" MyClass instances each time ... if that is an appropriate thing to do.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Didn't think of this, but seems like a decent way to go. Is it better generally to use factory methods instead of bare constructors? I've seen it being done in some libraries, but always preferred to have constructors when writing code myself. – Artyom Nov 12 '12 at 08:21
  • 1
    *"Is it better generally to use factory methods instead of bare constructors?"* - It is better to use what works best in the context of the application you are developing ... – Stephen C Nov 12 '12 at 11:40
1

If both A and B are interfaces, this would work

    public <T extends Object&A&B> MyClass(T arg)
    {
        this((B)arg);
    }

    new MyClass(null); // the 3rd constructor is chosen, which calls the 2nd
irreputable
  • 44,725
  • 9
  • 65
  • 93
  • Interesting solution, didn't know it was possible to have multiple bounds on `T` like that! +1 – Artyom Nov 12 '12 at 08:08