Interface to enforce generic static method in Java
我有一个Java类EDCOX1(0),它从我的远程数据库中建模一些数据。我希望项目中的所有数据模型都能够从
1 2 3 4 5 6 7 8 9 10 |
请注意,我将有几个模型(
1 2 3 | public interface DocParserSupplier<T> { static SnapshotParser<T> getDocParser(); } |
这不起作用的原因有两个(正如Android Studio告诉我的那样):
- 接口的
static 方法必须有默认实现。我不知道T 就做不到。 - 我得到"
T 不能在静态上下文中引用"的错误。
如果从上面的接口中删除
有Java的方式来做我想要的吗?
编辑:我的具体用例是将
1 2 3 4 5 6 | FirestoreRecyclerOptions<Model1> fro1 = new FirestoreRecyclerOptions.Builder<Model1>() .setQuery(query1, Model1.getDocParser()) .build(); FirestoreRecyclerOptions<Model2> fro2 = new FirestoreRecyclerOptions.Builder<Model2>() .setQuery(query2, Model2.getDocParser()) .build(); |
接口强制实例的行为,以便以类型安全的方式传递对具有该行为的任何对象的引用。另一方面,静态方法不属于对象的任何特定实例;类名本质上只是一个名称空间。如果要强制执行行为,则必须在某个地方创建实例(或者使用反射,如果绝对需要确保类具有特定的静态方法)。
除非这个系统将被打开进行扩展,在这里其他人可以定义他们自己的模型,否则我会说完全放弃DocParserSupplier接口,并像现在一样调用静态方法,或者将它们分解为工厂接口+实现。工厂选项很好,因为您可以用一个返回测试的虚拟解析器的伪实现替换生产实现。
编辑:文档分析器工厂
1 2 3 4 5 6 | public interface DocParserFactory { SnapshotParser<Model1> getModel1Parser(); SnapshotParser<Model2> getModel2Parser(); ... SnapshotParser<Model1> getModelNParser(); } |
…
1 2 3 4 5 6 7 8 9 10 11 12 | // The implementation of each getModelXParser method class DocParserFactoryImpl { SnapshotParser<Model1> getModel1Parser() { return docSnapshot -> { Map<String, Object> data = docSnapshot.getData(); return new Model(data.getOrDefault("name","John Doe"))}; } ... } |
…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private DocParserFactory docParserFactory; // You can inject either the real instance (DocParserFactoryImpl) or a // test instance which returns dummy parsers with predicable results // when you construct this object. public ThisObject(DocParserFactory docParserFactory) { this.docParserFactory = docParserFactory; } ... // Your code public void someMethod() { ... FirestoreRecyclerOptions<Model1> fro1 = new FirestoreRecyclerOptions.Builder<Model1>() .setQuery(query1, docParserFactory.getModel1Parser()) .build(); FirestoreRecyclerOptions<Model2> fro2 = new FirestoreRecyclerOptions.Builder<Model2>() .setQuery(query2, docParserFactory.getModel2Parser()) .build(); ... } |
与静态或非静态无关,这是因为如果不以某种方式传递类型参数,就无法创建泛型对象的实例。事实上,几天前我回答了一个类似的问题,当时有人想用枚举来获得所需的生成器。
简而言之,如果不以某种形式传递
在Java 8中,可以用方法引用来优雅地解决这个问题。我对Android不太了解,但我相信你仍然在Java 6上,所以这是行不通的。
不管怎样,您可以有如下内容:
1 2 3 4 5 6 7 8 | public <T extends AbstractBuilder> T builder(final Supplier<T> object) { return supplier.get(); } final Supplier<AbstractBuilder> model1BuilderSupplier = Model1Builder::new; builder(model1BuilerSupplier) .setQuery(query1, Model1.getDocParser()) .build(); |
这不完全是你想要的,但是你尝试去做的方式是行不通的。