Unexpected compile error when using the same method name but with different signatures using import static

For some reason I get a compile error when doing this:

package mypackage2;

public class YYY {

    public static void aMethod(int i, int j) {
        System.out.println("aMethod with Integers: " + i + " " + j);
    }
}

-

package mypackage;

import static mypackage2.YYY.*;

public class XXX {

    public XXX() {
        aMethod(1, 1); // <--- mypackage\XXX.java:8: error: method aMethod in class XXX cannot be applied to given types;
         //   aMethod(1, 1);
           // ^

    }

    private void aMethod(String s1, String s2) {
        System.out.println("aMethod with Strings: " + s1 + " " + s2);
    }

    public static void main(String[] args) {
        new XXX();
    }
}

Output:

$ javac mypackage/XXX.java mypackage2/YYY.java
mypackage\XXX.java:8: error: method aMethod in class XXX cannot be applied to given types;
                aMethod(1, 1);
                ^
  required: String,String
  found: int,int
  reason: actual argument int cannot be converted to String by method invocation conversion
1 error

However if I comment out:

private void aMethod(String s1, String s2) {
            System.out.println("aMethod with Strings: " + s1 + " " + s2);
        }

then there is no problem.

It's possible to do this when you extend another class that have the same method name, why isn't this possible when doing static imports?

Upvotes: 1

Views: 168

Answers (1)

Oleg Estekhin
Oleg Estekhin

Reputation: 8395

This is actually the expected behavior because in the scope of class XXX the name aMethod resolves to the XXX.aMethod(String, String) method.

You should check the JLS 6.4.1. Shadowing and JLS 15.12 Method Invocation Expression for explanation.

Using the shadowing rules

Shadowing describes a situation when an inner scope redefines a name from the outer scope, so that inside the inner scope the simple name refers to the entity from the inner scope and the fully qualified name is needed to refer to the entity from the outer scope.

The static import defines aMethod name in the file scope and XXX.aMethod declaration defines aMethod name in the scope of the XXX class. The method invocation occurs inside the scope of the XXX class so the simple name aMethod resolves to the XXX.aMethod.

Using the method invocation rules

The process of selecting the method is described in the JLS 15.12 Method Invocation Expression and it consists of three steps:

  1. select a class where to look for a method.
  2. select a particular method based on the argument types.
  3. check that everything is ok.

The first step involves checking whether some class that encloses the invocation point has a method with that name. The static imports are checked during the second step only if the first step did not find an applicable class.

Applying that to your example:

  • During the first step the XXX is selected because the invocation of the aMethod method is enclosed in the XXX class scope and XXX has a method with that name.
  • During the second step the XXX is searched for all methods with that name and each such method is checked whether it can be applied to the given list of arguments. There is no XXX.aMethod method that can take (int, int) arguments so compiler stops with the compilation error.

Upvotes: 1

Related Questions