Java 静态初始化

Java 静态初始化,java,instance-variables,static-initialization,Java,Instance Variables,Static Initialization,我编译代码时遇到了问题。当我编译代码时,foo2.var在类foo中返回null,我似乎不知道为什么。我在foo2类中进行静态初始化的方式是否有错误,导致foo2.var在foo类中为null 感谢您的帮助 public class foo extends bar { public final static String blah = foo2.var; ... } public abstract class bar { ... } public class foo2 exten

我编译代码时遇到了问题。当我编译代码时,foo2.var在类foo中返回null,我似乎不知道为什么。我在foo2类中进行静态初始化的方式是否有错误,导致foo2.var在foo类中为null

感谢您的帮助

public class foo extends bar {
  public final static String blah = foo2.var;
  ...
}

public abstract class bar {
  ...
}

public class foo2 extends bar {
  public final static String var;

  static {
    var = "newstring";
  }
  ...
}

在本例中,foo2.var行上出现空指针错误。

var
没有类型。Java中的常量按惯例也是大写的。让它:

public class Foo2 {
  public final static String VAR;

  static {
    VAR = "newstring";
  }
  ...
}

您尚未为
var
try
public final static String var指定类型

那为什么不

public class foo2 extends bar {
  public final static String var = "newstring";

您缺少
var
的类型,请将该行更改为以下内容:

public final static String VAR;
指定变量类型

此外,通过编码约定,类名应使用CamelCase和常量(带下划线的大写字母)编写

public class Foo2 {
   public final static VAR = "newstring"; // why not?
...
}
此外,您还可以通过一些变量来隐藏foo2类。检查您的导入。因为类静态字段引用无法生成NPE

访问静态字段(其值不是编译时常量表达式)将触发声明该字段的类的初始化,在此期间执行静态初始值设定项。但是,只有在初始化器之间没有循环依赖关系的情况下,才能保证在读取字段时完成初始化

例如,如果您运行该程序

class Bar {
    static final long bar;

    static {
        System.out.println("Assigning bar");
        bar = Foo.foo;
    }
}
class Foo extends Bar {
    static final long foo;

    static {
        System.out.println("Assigning foo");
        foo = 1;
    }
}

public class Test {
    public static void main(String[] args) {
        new Foo();
        System.out.println(Bar.bar);
    }
}
您将获得以下输出:

Assigning bar
Assigning foo
0
1
因为要创建
Foo
的新实例,
Foo.class
被初始化,它首先初始化它的超级类
Bar.class
,读取
Foo.class
的字段,但是
Foo.class
已经被初始化。Java语言规范要求这样的递归初始化立即完成,即调用方将看到类处于部分初始化状态。也就是说,
Foo.Foo
在读取时是未赋值的,因此仍然包含默认值0。该值被分配给
Bar.Bar
,完成
Bar.class
的初始化。然后,通过运行将
Foo.Foo
设置为1的初始值设定项,继续初始化
Foo.class


实际上,您可能希望检查类的依赖关系并构造程序,以便初始值设定项之间没有循环依赖关系。

什么类型的“var”?在运行
foo
之前是否编译了
foo2
?检查导入。如果foo2是在此上下文中导入的类,则它无法生成NPE!也许你用了什么东西来隐藏它,可能是null。@RohitJain我不确定,当编译器到达foo2.var行时,它返回null,我的理解是,当调用foo2 var实例变量时,它会自动在foo2 classI中运行静态初始化,我猜答案是“newstring”在foo2.var被分配给blah之后被分配给var。这些事情的顺序是在jls中指定的。糟糕,它在编译中确实有一个类型,只是忘了在示例中编写它。这会改变什么吗?常量不必是大写的,但这是标准约定。当然,您可以假定该类型是在那里给定的,否则编译器错误会有所不同。@RohitJain:是的,但问题中显示的代码没有其他错误。意思是也许我们应该问更多的细节糟糕的是,它在编译中确实有一个类型,只是忘了在示例中编写它。这会改变什么吗?你当然可以假设那里给出了类型,否则编译器的错误会不同。所以在你的例子中,您将如何更改它,以便在bar尝试访问它之前先为foo分配一个值?循环依赖性正是问题所在,我找到了一种方法,通过切换连接到我的示例的类/实例变量的设计来解决这个问题。谢谢