Thanks Campbell for your reply.
I ran all the 4 examples both using
IntelliJ and Online Java Compiler
(Programiz). I have attached the compilation results along with this message.
CASE 1: go()
I believe I’m satisfied with your feedback to first example. Not passing any argument to a method is considered 0-arity argument. Hence, it’s a clear match for the Object...
However, for the remaining three cases, I believe we can discuss as our results differ.I’ll cover each case one by one. It can be a bit long post but I tried to be as specific as possible.Please bear with me.
As per section 15.12.2. Compile-Time Step 2: Determine Method Signature of JLS, method overload resolution happens in three phases.
1.The first phase performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.
CASE 2: Now, when we use go(null);
As per your comment to second case,
Disagree. You are forgetting the arity of the arguments, so the one‑argument method takes precedence over the varargs method.
go(null) is a 1-arity method; so as per the above statement it should map to go(Object) rather than go(Object...) during first phase of overload resolution.since a variable arity method is treated as a fixed arity method in the first phase.
But I believe what’s going on here is: since null type has no explicit name and null reference can be cast to any other reference type. Hence, compiler can’t perfrom a widening reference conversion of null value in Phase 1. since it can be hypothetically widened to any reference type. Both go(Object) and go(Object...) are equally valid candidates for overload resolution in phase 1 as discovered by compiler.
RESULT: we have 2 potential applicable methods; so choose most specific method as per algorithm mentioned in
JLS 15.12.2.5. Choosing the Most Specific Method
I believe, the main decisive point for non-generic methods as per this
dreaded JLS section is to prefer specific type over general type; which in this case is Object... not Object.
Since all arrays are considered objects in java but not all java objects are arrays.
So, Object[ ] IS-A Object and hence, compiler chose the most specific method go(Object...) over go(Object) for the method call go(null).
That’s the output I got for CASE 2.
CASE 3: go(Object[ ])
if I consider the following code snippet:
Since, we’re explicitily providing the method argument of type Object[ ] (compiler knows the static type of variable obj at compile time)
Compiler uses the Strict Invocation Context rules of Phase 1 which allow use of identity conversion to choose a method.
5.1.1. Identity Conversion
A conversion from a type to that same type is permitted for any type.
Hence, compiler does overload resolution based on Identity conversion in this case and no need to go to Phase 2 and Phase 3.
So, I disagree with your following reply as code compiles based on above logic.
No. Since Object... is converted to Object[] inside the method, the compiler will perceive two methods which are override‑equivalent to each other and the code will fail to compile.
CASE 4: go(new String[ ]{"Coderanch", "is", "brilliant"});
I ran the code and it compiled fine running the Object... version of the method.
REASON: I believe at compile time, the argument expression which is an array creation expression is evaluated to be of type String[ ] in the method call go( new String[ ] {"Coderanch", "is", "brilliant"})
Now, during the first phase of the overload resolution, compiler looks for potentially applicable methods for the call go(String[ ]) using phase 1 Strict Invocation context rules.
Since, the array component type is String which is a reference type, compiler first applies the widening reference conversion for array type. In order to do widening reference conversion among array types,the following rule is followed:
As per section 4.10.3. Subtyping among Array Types of JLS
If S and T are both reference types, then S[ ] is a direct subtype of T[ ] iff S is a direct subtype of T.
Since String is a direct subtype of Object in java. Hence, String [ ] is a direct subtype of Object [ ]
Compiler found a method match in phase 1 and resolution process is over.
I believe that’s the reason in this case Object... will be chosen by compiler over Object. On compilation it’s chosing the Object... version in Case 4.
Please review my answer and suggest any improvement and guide me if possible regarding my approach.
Thanks