静态变量在声明之前如何访问?

发布于 2024-09-18 16:30:29 字数 295 浏览 10 评论 0原文

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

为什么我可以在课堂上使用 y,但不能直接使用?

y 是什么时候定义的?

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

How come I am allowed to use y trough the class, but not directly?

When is y defined?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

恋竹姑娘 2024-09-25 16:30:29

§8.3.2.3

8.3.2.3 初始化期间Fields的使用限制

会员声明需要
在使用之前以文本形式出现
仅当成员是实例时
(分别为static)类的字段
或接口 C 以及所有
满足以下条件:

  • 使用发生在实例(分别为静态)变量中
    C 的初始值设定项或实例中的初始值设定项
    (分别为static)初始化器
    C、
  • 用法不在作业的左侧。
  • 通过一个简单的名称即可使用。
  • C 是包含用法的最内部类或接口。

如果出现以下任一情况,则会发生编译时错误
上述四项要求均不成立
遇见了。

这意味着编译时错误
测试程序结果:

 类测试 {
      整数 i = j; // 编译时错误:前向引用不正确
      整数 j = 1;
  }

而下面的示例编译
没有错误:

 类测试 {
      测试(){ k = 2; }
      整数 j = 1;
      整数 i = j;
      整数 k;
  }

即使构造函数
测试的 (§8.8) 指的是
声明为三行的字段 k
稍后。

这些限制旨在
在编译时捕获循环或
否则初始化格式错误。
因此,两者:

<前><代码>Z类{
静态 int i = j + 2;
静态 int j = 4;
}

和:

<前><代码>Z类{
静态 { i = j + 2; }
静态 int i, j;
静态 { j = 4; }
}

导致编译时错误。
方法的访问未签入
这样,所以:

<前><代码>Z类{
静态 int peek() { 返回 j; }
静态 int i = peek();
静态 int j = 1;
}
类测试{
公共静态无效主(字符串[] args){
System.out.println(Zi);
}
}

产生输出:

<前><代码>0

因为 i 的变量初始值设定项
使用类方法peek来访问
j 之前变量 j 的值
已被其变量初始化
初始化程序,此时它仍然
有其默认值(§4.12.5).

The precise rules governing forward reference to class variables are described in the section §8.3.2.3 of the JLS:

8.3.2.3 Restrictions on the use of Fields during Initialization

The declaration of a member needs to
appear textually before it is used
only if the member is an instance
(respectively static) field of a class
or interface C and all of the
following conditions hold:

  • The usage occurs in an instance (respectively static) variable
    initializer of C or in an instance
    (respectively static) initializer of
    C.
  • The usage is not on the left hand side of an assignment.
  • The usage is via a simple name.
  • C is the innermost class or interface enclosing the usage.

A compile-time error occurs if any of
the four requirements above are not
met.

This means that a compile-time error
results from the test program:

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }

whereas the following example compiles
without error:

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }

even though the constructor
(§8.8) for Test refers to the
field k that is declared three lines
later.

These restrictions are designed to
catch, at compile time, circular or
otherwise malformed initializations.
Thus, both:

class Z {
  static int i = j + 2; 
  static int j = 4;
}

and:

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}

result in compile-time errors.
Accesses by methods are not checked in
this way, so:

class Z {
  static int peek() { return j; }
  static int i = peek();
  static int j = 1;
}
class Test {
  public static void main(String[] args) {
      System.out.println(Z.i);
  }
}

produces the output:

0

because the variable initializer for i
uses the class method peek to access
the value of the variable j before j
has been initialized by its variable
initializer, at which point it still
has its default value (§4.12.5).

猥琐帝 2024-09-25 16:30:29

我假设通过使用该类,编译器将推迟查找变量,直到该类完成,因此它找到 y,但如果您只是像注释一样定义它,则它尚未定义,因此会失败

I would assume that by using the class, the compiler would defer looking for the variable until the class was complete, so it finds y, but if you just define it like the comment it is not yet defined so it fails

如歌彻婉言 2024-09-25 16:30:29

静态变量在类加载期间按照类中声明的顺序定义。当 JVM 加载 Main 类时,将定义 x,然后定义 y。这就是为什么你在初始化x时不能直接使用y,你创建了一个叫做前向引用的东西,你引用了一个当前不是的变量定义了,这对于编译器来说是非法的。

当使用 Main.y 时,我认为会发生以下情况:

  • 您加载 Mainx 初始化被调用
  • 当您定义 x 等于 Main.y,编译器会看到对类的引用,因此它将结束将 x 定义为成员 y 的当前值类 Main。它将这种情况视为 Main 是一个不同的类。

请注意,在本例中,初始化x时,y暂时尚未定义。因此,x 的值为 0

Static variables are defined in order of declaration in the class, during class loading. When the JVM will load the Main class, x will be defined, then y. That's why you can't directly use y when initializing x, you create something that's called a forward reference, you refers to a variable not currently defined, and that's illegal for the compiler.

When using Main.y, I think the following happens:

  • You load Main, x initialization is called
  • When you define x to be equals to Main.y, the compiler sees a reference to a class, so it will end defining x to the current value of the member y of the class Main. It treats this case as if Main was a different class.

Note that in this case, when initializing x, y hasn't be defined for the moment. So x will have a value of 0.

眼眸印温柔 2024-09-25 16:30:29

你不被允许这样做,因为它毫无意义。唯一可能的解释是 y 被初始化为零,并且您已经有两种表达方式。你不需要这个。

You're not permitted to do it because it is meaningless. The only possible interpretation is that y is initialized to zero, and you already have two ways of saying that. You don't need this.

梦回梦里 2024-09-25 16:30:29

也许编译器在创建静态变量时会使用堆栈中的类创建具有默认值的静态变量的引用,然后分配提供的值。

Perhaps the compiler creates the references of the static variables with default values with the class in the stack, when it's created and then assigns the provided values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文