为什么我的 List<Long> 包含整数?
Why does my List<Long> contain integers?
所以,我有以下在本地伪造数据库的方法:
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<Long> 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:
这是学校信息 persisted/retrieved 来自的 DAO。问题发生在插入数据和删除数据之间的某个时间。它以 Long
类型输入,以 Int
类型输出
@Dao
public interface SchoolDao {
@Query("SELECT * FROM schools")
List<SchoolDto> getAllSchools();
@Insert
void insertSchool(SchoolDto schoolDto);
}
你看错变量了。 ClassDao实例在下面,你可以看到“{Long@6495}“1”。但是你传播的整数“1”是你代码中省略的ClassIds的元素。你确定ClassIds是List(),添加元素时,你应该做 classIds.add(new Long(1)).
哇,真是一场噩梦。我找到了罪魁祸首。
我创建了一个 TypeConverter
来将 List<Integer>
转换为一个字符串(并返回),这样它就可以存储在 room 数据库的单个列中,而无需修改现有的 DTO。但是,当我切换到使用 Long
类型作为 ID 时,我未能在转换器中转换下面的 单个 泛型参数;仔细看下面的代码:
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);
}
}
}
为了将来参考,此选角规则列表会对您有所帮助。本质上,我认为存在 is/was 隐式转换冲突。
byte –> short –> int –> long –> float –> double
你发现了你的问题:
Type resultType = new TypeToken<List<Integer>>(){}.getType();
return gson.fromJson(value, resultType);
(在方法 returning List<Long>
中)而它应该是:
Type resultType = new TypeToken<List<Long>>(){}.getType();
有一种类型安全的方法可以在编译时发现问题:
TypeToke<List<Integer>> resultTypeToken = new TypeToken<List<Integer>>() {};
return gson.getAdapter(resultTypeToken).fromJson(value);
这不会编译,因为 return 语句的类型与方法的 return 类型不兼容。
可能值得寻找 fromJson
的其他实例,这样您就可以迁移它们并查看是否还有您尚未发现的其他问题!
所以,我有以下在本地伪造数据库的方法:
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<Long> 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:
这是学校信息 persisted/retrieved 来自的 DAO。问题发生在插入数据和删除数据之间的某个时间。它以 Long
类型输入,以 Int
@Dao
public interface SchoolDao {
@Query("SELECT * FROM schools")
List<SchoolDto> getAllSchools();
@Insert
void insertSchool(SchoolDto schoolDto);
}
你看错变量了。 ClassDao实例在下面,你可以看到“{Long@6495}“1”。但是你传播的整数“1”是你代码中省略的ClassIds的元素。你确定ClassIds是List(),添加元素时,你应该做 classIds.add(new Long(1)).
哇,真是一场噩梦。我找到了罪魁祸首。
我创建了一个 TypeConverter
来将 List<Integer>
转换为一个字符串(并返回),这样它就可以存储在 room 数据库的单个列中,而无需修改现有的 DTO。但是,当我切换到使用 Long
类型作为 ID 时,我未能在转换器中转换下面的 单个 泛型参数;仔细看下面的代码:
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);
}
}
}
为了将来参考,此选角规则列表会对您有所帮助。本质上,我认为存在 is/was 隐式转换冲突。
byte –> short –> int –> long –> float –> double
Type resultType = new TypeToken<List<Integer>>(){}.getType();
return gson.fromJson(value, resultType);
(在方法 returning List<Long>
中)而它应该是:
Type resultType = new TypeToken<List<Long>>(){}.getType();
有一种类型安全的方法可以在编译时发现问题:
TypeToke<List<Integer>> resultTypeToken = new TypeToken<List<Integer>>() {};
return gson.getAdapter(resultTypeToken).fromJson(value);
这不会编译,因为 return 语句的类型与方法的 return 类型不兼容。
可能值得寻找 fromJson
的其他实例,这样您就可以迁移它们并查看是否还有您尚未发现的其他问题!