3

In this piece of code, why the compiler is not able to reference the method that has varargs argument from static context.

 private static void doSomething(int... nums) {
    System.out.println("1");
}
private void doSomething(int num1, int num2) {
    System.out.println("2");
} 

public static void main(String[] args) {
    doSomething(1,2);
}

JDK 17 is complaining Cannot make a static reference to the non-static method doSomething(int, int) . Is this a bug or another feature I am not aware of.

JDK 8 and JDK 11 dont complain about it!

Holger
  • 285,553
  • 42
  • 434
  • 765
anupamD
  • 862
  • 1
  • 8
  • 21
  • 1
    https://stackoverflow.com/questions/30573532/why-does-type-promotion-take-precedence-over-varargs-for-overloaded-methods !? Because the other method is a "better fit". – luk2302 Jun 28 '22 at 06:52
  • Javas overload resolution (the rules are complex, u can see them in the JLS) decided that the non-static variant is the better fit and should be called. But it cant be called because it is not static. – Zabuzard Jun 28 '22 at 06:53
  • JDK 8 and JDK 11 dont complain about it.. Is there any change in JLS – anupamD Jun 28 '22 at 06:55
  • you can't use non-static members inside a static method – Sidharth Mudgil Jun 28 '22 at 07:22
  • 1
    None of the answers here actually address the question asked. OP asks why there's a difference between Java 17 and Java 8 and 11. – MC Emperor Jun 28 '22 at 08:13
  • 2
    @MCEmperor now [there is one](https://stackoverflow.com/a/72785883/2711488) addressing the actual question… – Holger Jun 28 '22 at 11:52

4 Answers4

5

The behavior of rejecting the method invocation is correct. Method resolution should find the most specific method first and check for the static modifier afterwards.

But there is a bug in javac from version 7 to 16.

See

JDK-8268474, Method resolution should stop on static error

Javac is not in sync with section §15.12.3 of the JLS 16 specification. In particular, for invocations in static context, javac too early checks whether the method is static, and when it determines it is not static and cannot be called, proceeds to a further phase in method lookup, even though it should report a compile-time error.

This bug has been fixed with JDK 17.

Note that Eclipse’s compiler ECJ does not have this bug, so the example is rejected in Eclipse, regardless of which JDK version you use.

Only invocations using a simple name are affected. When you use ClassName.doSomething(1,2);, all versions will resolve the invocation to doSomething(int num1, int num2) and generate the correct error.

Holger
  • 285,553
  • 42
  • 434
  • 765
0

The doSomething method which takes two ints is an instance method and you are trying to call it without creating an instance of the object first.

Why should the compiler accept that? I highly doubt, that in any prior JDK it behaved differently.

Valerij Dobler
  • 1,848
  • 15
  • 25
0

A static method can call only other static methods; it cannot call a non-static method. So that's why the non-static doSomething function is always called.

In order to call the doSomething(int, int) you have to make it static or create an object of the class containing the method and then call the method using the object.

YourClass obj = new YourClass();
obj.doSomething(1, 2);
Sidharth Mudgil
  • 1,293
  • 8
  • 25
0

varargs are replacement for arrays. Compiler is giving you error because you are calling doSomething in a manner which is not acceptable for varargs:

To call your varargs method you should call something like:

doSomething(new int [] {1,2});

By this way, you will be correctly calling private static void doSomething(int... nums)

Tested this in JDK8 (8u41) & on JDK17.

Moreover, calling dosomething(1,2) is giving error on both JDK8 & JDK17 so I am not finding anything different on both versions.

Ashish Patil
  • 4,428
  • 1
  • 15
  • 36