Java &引用;变量xxx可能尚未初始化";调用静态方法时,该方法返回相同类型的变量以及该类型本身的相同名称

Java &引用;变量xxx可能尚未初始化";调用静态方法时,该方法返回相同类型的变量以及该类型本身的相同名称,java,jls,Java,Jls,为什么会出现如下所示的错误?我不确定在JLS中的何处可以找到这样做的限制 public class A { static A foo() { return null; } public static void main(String[] args) { A A = A.foo(); } } 编译时出错 A.java:14: error: variable A might not have been initialized

为什么会出现如下所示的错误?我不确定在JLS中的何处可以找到这样做的限制

public class A {

    static A foo() {
        return null;
    }

    public static void main(String[] args) {
        A A = A.foo();
    }
}
编译时出错

A.java:14: error: variable A might not have been initialized
        A A = A.foo();
              ^
1 error

该变量隐藏同名的类。这就是为什么会有这样的情况


正如Patricia在评论中指出的,这在JLS中实际上被称为:

在这些情况下,的规则指定将优先选择变量而不是类型,并且将优先选择类型而不是包


在您的例子中,会出现编译错误,因为变量隐藏了类型,因为声明是在方法调用之前处理的。这与执行以下操作相同:

public class A {
    public void foo() {
        String s = s.substring(0, s.length());
    }
}
您会遇到同样的错误:

A.java:3: variable s might not have been initialized String s = s.substring(0, s.length()); ^ 1 error 你认为输出是什么

$ javac A.java $ java A A.foo() $javac A.java $java A A.傅()
请参阅上的JLS,但我在JLS中找不到特定部分,该部分表示它是非法的,并且在类似这样的句子中,变量名隐藏了类型名。此外,如果我没有错,
=
操作符是从右向左求值的,因此编译器可以处理右边(变量不存在的地方),然后处理左边,这是变量声明和赋值,最后一个只是经验解释,编译器不向后读取。声明首先读取,在静态方法的情况下,可能用于推断RHS表达式中的类型,并且始终用于检查类型。它不仅仅是方法调用的副产品。而且,它本身并不是非法的,只是在这种情况下,您最终会得到一个不可编译的表达式。例如,对于2个类A和B,您可能会得到一个可编译程序,它与您认为的不一样。这里的主要线索是错误消息谈到“变量A”,并指向“A.foo()”中的“A”。这意味着编译器认为A是一个变量,而不是一种类型。而且,如果你给你的类和变量起了像
A
这样愚蠢的短名字,你就应该得到你得到的一切:-) $ javac A.java $ java A A.foo()