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

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));
问题根因
  1. 自定义Todo类没有重写toString()方法,所有打印逻辑最终调用的是Object类默认的toString()实现,该实现默认返回全类名@对象哈希值格式的内存地址字符串,不会输出类的实际属性值。
  2. 原有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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:06:08