Android Studio Log.d打印Cursor结果仅输出对象内存地址问题
问题描述
使用Log.d打印从Cursor读取封装的结果时,无法输出对象的实际内容,仅输出类似以下的对象内存地址信息:
D/Row values: com.example.androidlabs.Todo@7c9655f
对应实现代码如下:
public void printCursor(Cursor c) { // 获取数据库版本号 int version = db.getVersion(); // 获取Cursor行数 int rowCount = c.getCount(); // 获取Cursor列数 int columnCount = c.getColumnCount(); // 获取Cursor所有列名 String[] columnNames = c.getColumnNames(); // 存储每行读取结果的列表 ArrayList<Todo> rowValuesList = new ArrayList<>(); int ColIndex = c.getColumnIndex(myOpener.COL_1); int itemColIndex = c.getColumnIndex(myOpener.COL_2); int urgentColIndex = c.getColumnIndex(myOpener.COL_3); c.moveToFirst(); if(c.moveToFirst()) { long id = c.getLong(ColIndex); String item = c.getString(itemColIndex); int urgentInt = c.getInt(urgentColIndex); boolean urgent = urgentInt == 1; rowValuesList.add(new Todo(item, urgent, id)); } String rowValues = TextUtils.join(",", rowValuesList); // 打印所有变量到日志 Log.d("Database version", String.valueOf(version)); Log.d("Row count", String.valueOf(rowCount)); Log.d("Column count", String.valueOf(columnCount)); Log.d("Column names", Arrays.toString(columnNames)); Log.d("Row values", rowValues); }
已确认Cursor不为空,应用从SQLite加载对应结果后可以正常在界面展示,先后尝试以下方案均无法解决打印内存地址的问题:
// 方案1:直接打印列表toString Log.d("Row values", rowValuesList.toString());
// 方案2:遍历列表逐个打印对象 for (Todo t : rowValuesList) { Log.d("Row values", String.valueOf(t)); }
// 方案3:StringBuilder拼接后打印 StringBuilder s = new StringBuilder(); for(Todo todo : rowValuesList) { s.append(todo); s.append(","); } Log.d("Row values", String.valueOf(s));
问题根因
- 自定义
Todo类没有重写toString()方法,所有打印逻辑最终调用的是Object类默认的toString()实现,该实现默认返回全类名@对象哈希值格式的内存地址字符串,不会输出类的实际属性值。 - 原有Cursor遍历逻辑存在缺陷:重复调用了两次
c.moveToFirst(),且没有做循环遍历,只会读取Cursor中的第一行数据,无法拿到所有查询结果。
修复方案
- 第一步:在
Todo类中重写toString()方法,自定义需要输出的属性格式,参考实现:
public class Todo { // 原有属性、构造方法、其他业务逻辑保持不变 private long id; private String item; private boolean urgent; // 重写toString方法,自定义打印内容 @Override public String toString() { return "Todo{" + "id=" + id + ", item='" + item + '\'' + ", urgent=" + urgent + '}'; } }
- 第二步:修复Cursor遍历逻辑,通过循环读取所有行的数据,参考修正后的遍历代码:
ArrayList<Todo> rowValuesList = new ArrayList<>(); int ColIndex = c.getColumnIndex(myOpener.COL_1); int itemColIndex = c.getColumnIndex(myOpener.COL_2); int urgentColIndex = c.getColumnIndex(myOpener.COL_3); // 移除之前重复的c.moveToFirst()调用,通过do-while循环遍历所有行 if (c.moveToFirst()) { do { long id = c.getLong(ColIndex); String item = c.getString(itemColIndex); int urgentInt = c.getInt(urgentColIndex); boolean urgent = urgentInt == 1; rowValuesList.add(new Todo(item, urgent, id)); } while (c.moveToNext()); }
- 第三步:重写
toString()后,原有打印逻辑即可正常输出对象的实际内容,也可以直接通过以下方式打印全量列表:
Log.d("Row values", Arrays.toString(rowValuesList.toArray()));
内容的提问来源于stack exchange,提问作者user16064117
相关产品推荐
相关产品推荐

