【问题标题】:Why does my List<Long> contain integers?为什么我的 List<Long> 包含整数?
【发布时间】:2018-04-13 17:27:07
【问题描述】:

所以,我有以下方法在本地伪造数据库:

public class TestClassDao implements ClassDao {

    // ...

    private static List<ClassDto> classes = new ArrayList<>();

    @Override
    public List<ClassDto> getClassesByIds(List<Long> classIds) {
        List<ClassDto> results = new ArrayList<>();

        for (ClassDto classInstance : classes) {
            if (classIds.contains(classInstance.getId())) {
                results.add(classInstance);
            }
        }

        return cloner.deepClone(results);
   }

   //...

}

我很困惑,因为结果总是空空如也。我在 Android Studio 中逐步调试了调试器,发现包含检查始终返回 false,即使已知存在正确的 ID。

用调试器跟踪 那个,我发现我怀疑是罪魁祸首:根据调试器,List&lt;Long&gt; classIds 包含 *Integer* 对象。是什么赋予了?我不确定如何进一步调试。

编辑:

这是问题所基于的调试器输出:

编辑 2:

这是测试数据被加载到数据存储中的方式,您可以看到我正确地传递了Long 值:

下面的方法被一个对学校做类似事情的方法调用,然后通过测试DAO中的一个方法持久化。

public static ClassDto getClassTestData(int classId) {
    ClassDto classDto = new ClassDto();

    switch (classId) {
        case 1:
            classDto.setId(1L);
            classDto.setName("207E - Mrs. Randolph");
            classDto.setTeacher(getTeacherTestData());
            classDto.setStudents(getStudentsTestData());
            return classDto;
        case 2:
            classDto.setId(2L);
            classDto.setName("209W - Mr. Burns");
            classDto.setTeacher(getTeacherTestData());
            return classDto;
        case 3:
            classDto.setId(3L);
            classDto.setName("249E - Mr. Sorola");
            classDto.setTeacher(getTeacherTestData());
            return classDto;
        default:
            return null;
    }
}

编辑 3:

这里是保存/检索学校信息的 DAO。问题发生在插入数据和删除数据之间的某个时间。它以Long 类型输入,以Int 类型输出

@Dao
public interface SchoolDao {

    @Query("SELECT * FROM schools")
   List<SchoolDto> getAllSchools();

    @Insert
    void insertSchool(SchoolDto schoolDto);

    }

【问题讨论】:

  • getId() 是否返回Long
  • 是的,代码(用于 getter)在这里:public Long getId() { return id; }
  • 您用来执行查询的工具正在为相关列生成一个Integer 对象。您需要使用整数列表或告诉数据库访问工具您希望该值为 Long。
  • 您如何填充List?他们进入列表时是Long吗?
  • classIds 是一个参数,并且不会被此方法更改,因此传入时整数就在其中。我猜想某处有对列表的原始引用,并且list.add(123) 之类的事情正在发生,而不是 123L

标签: java android android-room


【解决方案1】:

哇,真是一场噩梦。我找到了罪魁祸首。

我创建了一个TypeConverter 来将List&lt;Integer&gt; 转换为字符串(并返回),这样它就可以存储在房间内数据库的单个列中,而无需修改现有的DTO。但是,当我切换到使用 Long 类型作为 ID 时,我未能在转换器中转换下面的 single 通用参数;仔细看下面的代码:

public class IdsListConverter {

    @TypeConverter
    public List<Long> idsFromString(String value) {
        Gson gson = new Gson();
        if (value == null || value.isEmpty()) {
            return null;
        } else {
            Type resultType = new TypeToken<List<Integer>>(){}.getType();
            return gson.fromJson(value, resultType);
        }
    }

    @TypeConverter
    public String idsToString(List<Long> ids) {
        if (ids == null) {
            return null;
        } else {
            Gson gson = new Gson();
            return gson.toJson(ids);
        }
    }

}

【讨论】:

  • "仔细看" 请说明你做了什么来修复它。
  • Type resultType = new TypeToken&lt;List&lt;Integer&gt;&gt;(){}.getType(); 应该将泛型更改为 List&lt;Long&gt;
  • 因此,请在答案中声明,不要让那些不知道应该“仔细查看”什么的读者感到疑惑。另外,请注意 gson.getAdapter(new TypeToken&lt;List&lt;Integer&gt;&gt;(){}).fromJson(value) 将是一个类型安全的选项(假设这是一个 com.google.gson.reflect.TypeToken)。
【解决方案2】:

It looks like你发现了你的问题:

Type resultType = new TypeToken<List<Integer>>(){}.getType();
return gson.fromJson(value, resultType);

(在返回 List&lt;Long&gt; 的方法中)而应该是:

Type resultType = new TypeToken<List<Long>>(){}.getType();

有一种类型安全的方式来编写它,它会在编译时发现问题:

TypeToke<List<Integer>> resultTypeToken = new TypeToken<List<Integer>>() {};
return gson.getAdapter(resultTypeToken).fromJson(value);

这不会编译,因为返回语句的类型与方法的返回类型不兼容。

可能值得寻找其他出现的fromJson,以便您可以迁移它们,看看是否还有其他尚未发现的问题!

【讨论】:

  • 优秀的答案!没想到我能做到。
【解决方案3】:

您查看了错误的变量。 ClassDao 实例在下面,你可以看到 "{Long@6495} "1"。但是你传播的 Integer "1" 是 ClassIds 的元素,在你的代码中被省略了。你确定 ClassIds 是 List(),添加元素时,你应该做 classIds.add(new Long(1))。

【讨论】:

  • 在将列表粘贴到本地 DB schoolDto.setClassIds(Arrays.asList(1L, 2L, 3L)); 之前,我使用以下行初始化列表
  • 当你将classids存入数据库时​​,你能找出数据库中的数据类型吗?因为在 sqlite 中没有 long 类型
  • 它是用 Room ORM 完成的,所以我认为它可以处理?
  • stackoverflow.com/a/12584590/3908814我们知道sqlite使用整数来保存long。我建议您在从数据库中获取时尝试通过强转换为 long 来初始化您的 classId。
  • 您的意思是在从数据库中检索时手动从 int 转换为 long 吗?
【解决方案4】:

为了将来参考,这个施法规则列表将对您有所帮助。从本质上讲,我相信存在/曾经存在隐含的强制转换冲突。

byte –> short –> int –> long –> float –> double

【讨论】:

  • 感谢您的帮助,但这不是问题所在。我已经回答了实际的问题。
猜你喜欢
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多