TL; DR:如何正确使用Firebase DataSnapshot.getValue()的泛型类?
用例:我想使用Firebase为我的所有实体(其中一组)实现单个通用远程数据源类。在收听数据更改时,我希望将datasnapshot中的值作为E类型的对象(其类型在别处确定),但我不知道它是否可以使用Firebase查询,如下所示:
public class GenRemoteDataSource<E extends SomeClass>
{
//...
public void onDataChange(DataSnapshot dataSnapshot)
{
E item = (E) dataSnapshot.getValue(); // <- unchecked cast and it doesn't work
items.add(item);
}
}
例如,我有一个扩展SomeClass的Foo类,并且这个GenRemoteDataSource的实现与一个Foo类将是:
public class Foo extends SomeClass{}
public class FooRemoteDataSource extends GenRemoteDataSource<Foo>
{
//...
}
但Firebase会抛出运行时错误,因为它不会将getValue()强制转换为Foo,而是尝试将值转换为上限SomeClass。我很困惑为什么会这样:
Java.lang.ClassCastException: java.util.HashMap cannot be cast to com.example.app.SomeClass
请告知我应该如何使用Type-safety(没有未选中的演员表)。谢谢。
编辑以下内容与此无关,请参阅GenericTypeIndicator
<击> 的修改 我也试过(盲目地,值得一试)GenericTypeIndicator,
GenericTypeIndicator<E> mTypeIndicator = new GenericTypeIndicator<>();
E item = dataSnapshot.getValue(mTypeIndicator);
但它反而吐出以下运行时错误。
com.google.firebase.database.DatabaseException: Not a direct subclass of GenericTypeIndicator: class java.lang.Object
击> <击> 撞击>
答案 0 :(得分:2)
TL; DR我的解决方案,(引入更多的依赖性而不是语义上必需的?)
public class GenRemoteDataSource<E extends SomeClass>
{
//...
private final Class<E> clazz;
GenRemoteDataSource(Class<E> clazz)
{
this.clazz = clazz;
}
//...
public void onDataChange(DataSnapshot dataSnapshot)
{
E item = dataSnapshot.getValue(clazz); // <- now is type safe.
items.add(item);
}
}
我最后通过构造函数注入向getValue()提供了类定义。这是通过将Class<T>
传递给泛型类的构造函数并将其设置为Firebase的getValue()以用作实例参数来完成的。请评论是否有更好的解决方案,因为对我来说这似乎是多余的。谢谢!