简体   繁体   English

解决静态方法歧义

[英]Resolving static method ambiguity

I have been working on understanding java compilation and I have come across a question. 我一直在努力理解java编译,我遇到了一个问题。 Say we have a class set up like this 假设我们有这样的课程设置

public class Ambiguity 
{
    static class G
    {
        void A()
        {
            System.out.println("Regular Method");
        }
    }

    static class b
    {
        static void A()
        {
            System.out.println("Static Method");
        }
    }

    public static void main(String[] args)
    {

        G b = new G();
        b.A();
    }
}

How does the compiler know weather to call the method static void A() in the class b or the regular method void A() on the object b of type G . 编译器如何知道在class b调用方法static void A()或在类型G的对象b上调用常规方法void A()天气。 Based on tests I ran it appears to call the object b (of type G ) method but I did not know if this is always standard procedure. 基于我运行的测试它似乎调用对象b (类型G )方法,但我不知道这是否始终是标准过程。 In this situation how could the static method be called. 在这种情况下,如何调用静态方法。

  • The local variable, named b and of type G , 局部变量,名为b ,类型为G
  • " obscures " the name of the type b anywhere where the variable b is in scope . 隐藏 ”变量b 在范围内的任何位置的类型b的名称。
  • The method on the type b is therefore not called. 因此不调用类型b上的方法。

The obscuring occurs as the local scoped variable is more specific. 由于本地范围变量更具体,因此会出现模糊现象。 The rules for obscuring are complex, but summarised in JLS §6.4.2 : 模糊的规则很复杂,但在JLS§6.4.2中进行了总结:

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package . 一个简单的名称可能出现在上下文中, 它可能被解释为变量,类型或包的名称 In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type , and that a type will be chosen in preference to a package. 在这些情况下, §6.5的规则指定将优先选择变量而不是类型 ,并且将优先选择类型而不是包。 Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. 因此,有时可能无法通过其简单名称引用可见类型或包声明。 We say that such a declaration is obscured . 我们说这样的声明是模糊的

Obscuring like this is bad practice and should be avoided. 这样的模糊是不好的做法,应该避免。 However you can work around the ambiguity in this case by providing a qualified name ( §6.2 ) for the type. 但是,在这种情况下,您可以通过为类型提供限定名称第6.2节 )来解决模糊问题。 This changes the applicable name selection rule from §6.5 : 这会更改§6.5中适用的名称选择规则:

G b = new G();
Ambiguity.b.A(); // calls Ambiguity.b.A()
b.A();           // calls Ambiguity.G.A() on variable b

Prints: 打印:

Static Method
Regular Method

~~~~ ~~~~

Specifically, the unqualified name b in this context is classified initially as an Ambiguous Name ( §6.5.1 ). 具体而言,此上下文中的非限定名称b最初被分类为不明确名称 (第6.5.1节 )。 It is then reclassified by the priority rule from §6.5.2 (bold is my highlighting, italics is my addition): 然后根据§6.5.2中的优先级规则对其进行重新分类(粗体是我的突出显示,斜体是我的补充):

If the AmbiguousName is a simple name, consisting of a single Identifier 如果AmbiguousName是一个简单的名称,由一个标识符组成

• If the Identifier appears within the scope ( §6.3 ) of a local variable declaration (§14.4) or parameter declaration (§8.4.1, §8.8.1, §14.20) or field declaration (§8.3) with that name, then the AmbiguousName is reclassified as an ExpressionName ( ... as opposed to a TypeName, from the lower priority rule 3 ). •如果标识符出现的范围内( §6.3 )的局部变量的声明(§14.4)或参数声明(§8.4.1,§8.8.1,§14.20)或字段声明(§8.3)具有该名称,然后AmbiguousName被重新分类为ExpressionName...而不是TypeName,来自较低优先级规则3 )。

The "best match" will be called. 将调用“最佳匹配”。 Objects are more precise than static methods, and as such object methods will be used by default; 对象比静态方法更精确,因此默认情况下将使用对象方法; you can call a static method via Class.Method(); 你可以通过Class.Method();调用静态方法Class.Method(); . What's actually wrong here is that your local variable b happens to have the same name as the class, and as such, it is hiding the class. 这里真正错误的是你的局部变量b恰好与类同名,因此它隐藏了类。

You can still call the class static method if you use the full path: Ambiguity.bA(); 如果使用完整路径,仍然可以调用类静态方法: Ambiguity.bA();

In this case to resolve the ambiguity you should call: 在这种情况下,要解决歧义,你应该调用:

Ambiguity.b.A();

Java gives preference for variables with smaller scope. Java优先考虑范围较小的变量。 In this case Ambiguity.b is not really a variable but has global scope since It doesn't belong to an instance object. 在这种情况下,Ambiguity.b实际上不是一个变量,但具有全局范围,因为它不属于实例对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM