5

For example, a class include two methods,

public void find(Object id);
public void find(Object... ids);

When I invoking find(null), why jvm actually execute the last one?

In accepted answer of Calling Java varargs method with single null argument? we can read that

Java doesn't know what type it is supposed to be. It could be a null Object, or it could be a null Object array. For a single argument it assumes the latter."

but that still doesn't explain it. Can anyone provide some more information like from language specification?

Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • 3
    Because `Object[]` is more specific type than `Object`. See [JLS §15.12.2](https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.2). – apangin Jan 12 '19 at 13:27
  • 1
    @apangin you should post that as an answer –  Jan 12 '19 at 15:19
  • Not an answer - but Is there any point in defining find(Object)? Presumably the single-argument implementation produces identical results to the varargs implementation with a single argument. Or is it somehow more efficient to have an implementation specialized for a single arg? –  Jan 12 '19 at 15:21
  • @another-dave If I remember correctly, efficiency was the reason why aside of `List.of​(E... elements)` we also have `List.of(E e)` `List.of(E e1, E e2)` ... until `List.of([..], E e9, E e10)`. – Pshemo Jan 12 '19 at 22:22

1 Answers1

2

Object[] is more specific type than Object.

According to JLS §15.12.2

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.

The same chapter also has an example exactly about the situation in question.

[...] a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.

apangin
  • 92,924
  • 10
  • 193
  • 247
  • It may be worth mentioning that JVM thinks that Object[] is more specific than Object simply because Object is supertype of any array type. – Pshemo Jan 12 '19 at 22:24
  • @Pshemo …and the historical relationship between varargs and arrays. If varargs weren’t arrays, we didn’t have the problem. But since they are, we have to keep the compatibility to the overloading resolution rules existing before the introduction of varargs. – Holger Jan 14 '19 at 12:33