You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何代码有时抛出ExceptionInInitializerError?静态变量res为空原因排查

为什么静态初始化的Resources会抛出空指针?

这个问题其实是Android中类加载时机和Application生命周期顺序的经典坑!我来帮你拆解一下:

问题根源

你的代码里存在一个关键的时序冲突:

  • GameActivity的静态变量res和foo是在类被ClassLoader加载时就执行初始化的
  • 而App类的context是在Application.onCreate()方法里才赋值的,这个方法是Android系统在创建Application实例后才会调用的

但Android应用启动时,类的加载时机是不确定的——如果GameActivity类在App.onCreate()执行之前就被加载了(比如其他组件提前引用了它的静态成员,或者系统预加载了该类),那么App.getAppContext()返回的就是null,调用getResources()自然就会触发空指针,进而导致foo初始化失败,抛出ExceptionInInitializerError。

简单说就是:静态变量初始化的时间早于Application上下文的初始化时间,所以拿到了空的Context。

解决方法

这里有几个靠谱的修复方案:

方案1:懒加载静态资源

把静态变量的初始化延迟到第一次使用的时候,而不是类加载时:

public class GameActivity extends Activity {
    private static Resources res;
    private static String foo;

    public static String getFoo() {
        // 第一次使用时才初始化
        if (res == null) {
            res = App.getAppContext().getResources();
        }
        if (foo == null) {
            foo = res.getString(R.string.foo);
        }
        return foo;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 也可以在这里提前初始化,因为此时Application的onCreate已经执行完毕
        if (res == null) {
            res = getResources();
            foo = res.getString(R.string.foo);
        }
    }
}

方案2:在Application中提前初始化资源

既然Application的onCreate()是所有Activity启动前一定会执行的,那可以把需要的资源字符串放在这里初始化:

public class App extends Application {
    private static Context context;
    public static String FOO_STRING; // 直接在这里初始化全局资源

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        // 此时Context已经完全可用,直接初始化资源
        FOO_STRING = context.getString(R.string.foo);
    }

    public static Context getAppContext() {
        return context;
    }
}

之后在GameActivity里直接用App.FOO_STRING就可以了,完全避免静态初始化的时序问题。

方案3:避免使用静态资源依赖Context

如果不是必须要用静态变量,那最好在Activity的生命周期方法(比如onCreate())里获取资源,这样Context肯定是有效的:

public class GameActivity extends Activity {
    private String foo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        foo = getResources().getString(R.string.foo);
    }
}

总结

本质上要记住:永远不要在静态初始化块/静态变量赋值中依赖Android的Context,因为此时Context很可能还没初始化完成。改用懒加载、Application全局初始化或者在组件生命周期内获取,才是安全的做法。

内容的提问来源于stack exchange,提问作者activity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:05:46