使用相同的方法名称但使用import static使用不同签名时出现意外的编译错误

时间:2014-04-04 13:10:38

标签: java inheritance compiler-errors override

出于某种原因,我在执行此操作时遇到编译错误:

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();
    }
}

输出:

$ 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

但如果我发表评论:

private void aMethod(String s1, String s2) {
            System.out.println("aMethod with Strings: " + s1 + " " + s2);
        }
那么没有问题。

当您扩展另一个具有相同方法名称的类时,可以这样做,为什么在进行静态导入时这不可能?

1 个答案:

答案 0 :(得分:1)

这实际上是预期的行为,因为在类XXX的范围内,名称aMethod解析为XXX.aMethod(String, String)方法。

您应该查看JLS 6.4.1. ShadowingJLS 15.12 Method Invocation Expression以获取解释。

使用阴影规则

阴影描述了内部作用域从外部作用域重新定义名称时的情况,因此在内部作用域内,简单名称是指内部作用域中的实体,需要完全限定名称来引用该作用域中的实体。外部范围。

静态导入在文件范围中定义aMethod名称,XXX.aMethod声明在aMethod类的范围内定义XXX名称。方法调用发生在XXX类的范围内,因此简单名称aMethod将解析为XXX.aMethod

使用方法调用规则

选择方法的过程在JLS 15.12 Method Invocation Expression中描述,它包含三个步骤:

  1. 选择要在哪里查找方法的类。
  2. 根据参数类型选择特定方法。
  3. 检查一切正常。
  4. 第一步涉及检查包含调用点的某个类是否具有该名称的方法。如果第一步没有找到适用的类,则在第二步 期间检查静态导入。

    将其应用于您的示例:

    • 在第一步中选择了XXX,因为aMethod方法的调用包含在XXX类范围内,XXX有一个具有该名称的方法。
    • 在第二步中,XXX搜索具有该名称的所有方法,并检查每个这样的方法是否可以应用于给定的参数列表。没有XXX.aMethod方法可以使用(int, int)参数,因此编译器因编译错误而停止。