java.lang.RuntimeException: Unable to start receiver comm.GetuiReceiver: java.lang.NullPointerException
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2287)
...
Caused by: java.lang.NullPointerException
at comm.GetuiReceiver.onReceive(GetuiReceiver.java:140)
...
switch (bundle.getInt(PushConsts.CMD_ACTION)) {
case PushConsts.GET_CLIENTID:
comm_frame.dev.client_id = bundle.getString("clientid"); // 第 140 行
break;
}
錯誤提示:comm_frame.dev.client_id 已聲明但未初始化。嘗試先賦值 null 再賦值字符串仍報錯。
comm_frame.dev.client_id 是三級鏈式引用:
comm_frame — 必須是一個已實例化的對象引用。dev — comm_frame 的成員,必須已實例化(非 null)。client_id — dev 的 String 字段,賦值前可為 null。異常拋在 comm_frame.dev.client_id = ... 這一行,說明 comm_frame 為 null,或 comm_frame.dev 為 null。Java 中對 null 引用訪問成員(字段或方法)會拋 NPE,與目標字段是否初始化無關。
檢查 comm_frame 是否在 GetuiReceiver 類中聲明並實例化:
public class GetuiReceiver extends BroadcastReceiver {
// 必須有實例化,如:
CommFrame comm_frame = new CommFrame(); // 或通過依賴注入、單例獲取
// 或靜態引用:CommFrame comm_frame = CommFrame.getInstance();
@Override
public void onReceive(Context context, Intent intent) {
// ...
}
}
若 comm_frame 僅聲明 CommFrame comm_frame; 未賦值,則為 null。
即使 comm_frame 非 null,其內部 dev 字段也必須實例化:
public class CommFrame {
public Dev dev = new Dev(); // 必須在構造函數或字段初始化時 new Dev()
// ...
}
public class Dev {
public String client_id; // 字段可為 null,賦值時無需先 new String
// ...
}
// 在 onReceive 內部安全賦值
if (comm_frame != null && comm_frame.dev != null) {
comm_frame.dev.client_id = bundle.getString("clientid");
} else {
Log.e("GetuiReceiver", "comm_frame 或 dev 為 null,無法設置 client_id");
// 可選:初始化它們
if (comm_frame == null) comm_frame = new CommFrame();
if (comm_frame.dev == null) comm_frame.dev = new Dev();
comm_frame.dev.client_id = bundle.getString("clientid");
}
Dev dev; 只是一個引用變量,默認 null,必須 new Dev() 分配內存。a.b.c = 1 中,a 或 a.b 為 null 都會在訪問下一級時崩潰。client_id = "abc" 即可,client_id = null; client_id = "abc" 多餘且無法解決上層 null 問題。在崩潰行前加斷點或日誌:
Log.d("DEBUG", "comm_frame=" + comm_frame);
Log.d("DEBUG", "comm_frame.dev=" + (comm_frame != null ? comm_frame.dev : "N/A"));
即可直觀看到哪一層為 null,針對性初始化即可解決。