問題描述
今天寫bug代碼的時候有一個List< Date >類型的集合在使用getTime()方法時出現了空指針異常,日誌提示java.lang.NullPointerException: Attempt to invoke virtual method ‘long java.util.Date.getTime()’ on a null objectreference,本意是把一個活動中List< String >類型的時間集合直接用bundle傳遞給另一個活動HistoryActivity,再將類型轉換爲List< Date >使用,結果在接收的活動中使用Date.getTime()方法獲取時間時一直報空指針。
代碼
//傳值的活動
Intent history=new Intent(MainActivity.this,HistoryActivity.class);
Bundle bundle = new Bundle() ;
bundle.putStringArrayList("DATA", history_times);
Log.d(TAG,"myhistorytimes"+history_times.toString());
history.putExtras(bundle) ;
startActivity(history) ;
//取值的活動
Intent intent = getIntent() ;
Bundle bundle=intent.getExtras();
ArrayList<String> recvData = new ArrayList<>();//收到的數據
if (bundle != null) {
recvData = (ArrayList<String>)bundle.getStringArrayList("DATA");
Log.d(TAG,"myhistorytimes"+recvData.toString());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd/hh:mm:ss");//時間的格式
ParsePosition pos = new ParsePosition(0);
history_times.clear();
for (String aRecvData : recvData) {
Date strtodate = formatter.parse(aRecvData, pos);
history_times.add(strtodate);
}
Log.d(TAG,"onCreate myhistorytimes before"+history_times.toString());
//使用List<Date> history_times時報錯
try {
if(history_times!=null){
Log.d(TAG,"myhistorytimes getLineData good "+history_times.toString());
for(Date d:history_times){
String time2 = new SimpleDateFormat("yyyy/MM/dd").format(d.getTime());
if(time1.equals(time2)){ //比較兩個時間
value++;
section_count++;
}
}
xValues.add(time1);
yValues.add(new Entry(value, i));
}
}catch (Exception e) {
Log.d(TAG,"myhistorytimes getLineData bad "+data.toString());
Log.e(TAG,"myhistorytimes"+e.toString());
}
問題分析
從輸出的log中可以發現我的數據在傳之前有五個值,傳到之後也有五個具體的值,但是在使用時五個值只有第一個有具體值,餘下的都是null,在進入到HistoryActivity時直接閃退,用stackoverflow上的方法捕獲異常之後代碼可以正常運行不閃退,但是依然不能獲取到正確的數據stackoverflow:Attempt to invoke virtual method ‘long java.util.Date.getTime()’ on a null objectreference
所以問題大概率是出在把List < String >類型轉換爲List < Date >時,只有第一個值成功加到了List < Date > history_time中。(到處加Log.d標籤找了好久才找到問題所在,論Log的重要性)
問題求解
問題在於ParsePosition pos = new ParsePosition(0)這裏,本來以爲ParsePosition 像SimpleDateFormat 一樣在前面聲明和初始化之後,後面每個值都能共用他們,但是實際上ParsePosition對象相當於是一個索引參數記錄當前位置,所以不同的對象在使用ParsePosition處理格式時都要重新new一個ParsePosition,不能共用。
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd/hh:mm:ss");//時間的格式
ParsePosition pos = new ParsePosition(0);
history_times.clear();
for (String aRecvData : recvData) {
Date strtodate = formatter.parse(aRecvData, pos);
history_times.add(strtodate);
}
ParsePosition類說明
所以應該把ParsePosition pos = new ParsePosition(0)放在for循環裏面,對取到的每一個值都單獨進行類型轉換。
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd/hh:mm:ss");//時間的格式
history_times.clear();
for (String aRecvData : recvData) {
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(aRecvData, pos);
history_times.add(strtodate);
}
如圖,不再報錯,而且可以取到正確的值,問題得解。