【问题标题】:Java Legal Forward ReferencingJava 合法前向引用
【发布时间】:2012-04-05 20:55:55
【问题描述】:

以下代码是合法前向引用的情况吗?如果是,为什么?

public class MyClass
{
  private static int x = getValue();
  private static int y = 5;
  private static int getValue()
  {
    return y;
  }
  public static void main(String[] args)
  {
    System.out.println(x);
  }
}

【问题讨论】:

    标签: java reference forward static-initialization


    【解决方案1】:

    您拥有的上述代码是完全合法的 Java。在 Java 中,静态字段的初始化如下:首先,将所有字段设置为其类型的默认值(0、falsenull),然后按照它们声明的顺序进行初始化。这意味着上面的代码可以保证执行以下操作:

    1. xy 设置为零,因为这是ints 的默认值。
    2. 通过调用getValue()来初始化x,它读取y的值。由于y 尚未初始化,它的值仍然为 0。
    3. y初始化为5。

    这意味着x 将采用值0,y 将采用值5。这种行为是可移植的且有保证的。 You can see this here

    希望这会有所帮助!

    【讨论】:

    • 如果不是静态变量和方法会怎样?
    • 我相信行为是一样的——初始化是首先将所有内容设置为默认值,然后用指定的值初始化每个,然后调用构造函数。
    • 顺便说一句,这是你永远不应该从构造函数调用非最终(或私有)方法的原因之一;有人很容易覆盖该方法并看到尚未构造的this,甚至看到未初始化的最终字段。
    • 您的答案是否与下面的答案相反,您会在私有静态 int x=y 中得到前向引用错误;私有静态int y = 5; ?
    • @user1186046- Java 允许您间接拥有一个变量前向引用另一个,但不允许您直接拥有一个变量前向引用其他。 OP的代码没有直接设置x等于y,所以没有错误。但是,您是对的,您的代码版本会给出前向引用错误。
    【解决方案2】:

    你可以通过它编译的事实来判断它是否合法;与其他一些语言不同,Java 没有“未定义行为”的概念。这里发生的事情已经完全说明。这可能违反直觉,但它特别合法:您可以在从初始化另一个静态变量时调用的方法初始化静态变量之前访问它。直接从x 的初始化程序访问y 的表面相似的情况——即,

    private static int x = y;
    private static int y = 5;
    

    是明确禁止的。真的没有什么强有力的理由——它就是这样。

    【讨论】:

    • 如果变量是非静态的怎么办..在这种情况下行为也一样吗?
    • 是的,实际上是一样的。为静态列出的规则略有不同,因为类没有实际的“构造函数”,但对象的初始化方式基本相同。例如,实例变量、初始值设定项和实例块按出现顺序附加到每个构造函数。对于静态,初始化程序和静态块按顺序编译成一个名为 <clinit>() 的方法。
    • 当涉及到这样的问题时,恐怕拥有一个可以用编译器测试的程序是一种奢侈。这取自 OCJP 考试的模拟考试。我现在正在学习它,正是这些愚蠢的问题完全没有意义,使考试的意图成为一种嘲弄。
    猜你喜欢
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 2011-08-06
    相关资源
    最近更新 更多