Java:静态最终字段的初始化顺序是什么?
好的,假设我有一个这样的类:Java:静态最终字段的初始化顺序是什么?,java,static,initialization,classloader,final,Java,Static,Initialization,Classloader,Final,好的,假设我有一个这样的类: public class SignupServlet extends HttpServlet { private static final Logger SERVLET_LOGGER=COMPANYLog.open(SignupServlet.class); private static final ExceptionMessageHandler handler = new ExceptionMessageHandler(); priv
public class SignupServlet extends HttpServlet {
private static final Logger SERVLET_LOGGER=COMPANYLog.open(SignupServlet.class);
private static final ExceptionMessageHandler handler = new ExceptionMessageHandler();
private static final SignupServletObservableAgent signupObservableAgent =
new SignupServletObservableAgent(null, SERVLET_LOGGER);
}
我是否可以依靠类加载器按顺序初始化这些字段,这样我就可以依靠SERVLET\u LOGGER在注册ObservableAgent之前进行实例化?是的,它们是按它们在源代码中出现的顺序初始化的。你可以在中阅读所有血淋淋的细节。参见步骤9,内容如下: 。。。以文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就像它们是单个块一样,但值为编译时常量的最终类变量和接口字段首先初始化
我认为静态字段的初始化可以重新排序。至少我是这样理解的 在许多情况下,对程序变量(对象实例字段、类静态字段和数组元素)的访问的执行顺序可能与程序指定的顺序不同
如果存在子类和超类
这是一个可以使用静态块来保证执行顺序的地方
public class SignupServlet extends HttpServlet {
private static final Logger SERVLET_LOGGER;
private static final ExceptionMessageHandler handler;
private static final SignupServletObservableAgent signupObservableAgent;
static {
SERVLET_LOGGER = COMPANYLog.open(SignupServlet.class);
handler = new ExceptionMessageHandler();
signupObservableAgent = new SignupServletObservableAgent(null, SERVLET_LOGGER);
}
}
不是真的回答这个问题,而是在这里问更多-。刚刚遇到一个有趣的静态字段初始化顺序示例。以下是一个例子:
public class Foo {
private static final Long result = method1();
private static String string = "something";
private static Long method1() {
if (string == null) {
throw new IllegalStateException("BOOM");
}
return 1L;
}
public static void main(String[] args) {
System.out.println("here");
}
}
这将产生非法状态例外。我知道这里的顺序是首先计算“result”字段,它调用method1()并绕过“string”值初始化。“string”是一个常量,但我在编写测试时忘了放一个“final”修饰符。但是这种情况是否应该在运行时处理?这意味着当我们调用“if(string==null)”时,JRE是否应该足够聪明去验证“string”是否还没有初始化并初始化它 这一部分还指出“…b的值不依赖于a的值,那么编译器可以自由地对这些操作重新排序,…”引用的是访问,而不是初始化。