所以我得到了一个接口SuperType
和一堆实现类TypeA
,TypeB
等等。我还有一个顶级接口,它有一个参数化方法:
public interface UsedByProductThing<T extends SuperType> {
public T doStuff(T one);
}
我有一个工厂(见下文),生成实现GeneralProduct
的对象:
public interface GeneralProduct<T extends SuperType> {
T doSomething(T input);
}
以下是实施ProductA
:
public class ProductA implements GeneralProduct<TypeA> {
UsedByProductThing<TypeA> in;
public ProductA(UsedByProductThing<TypeA> in) {
this.in = in;
in.doStuff(new TypeA());
}
@Override
public TypeA doSomething(TypeA input) {
return null;
}
}
现在有问题的工厂:
public class GeneralFactory {
public static <T extends SuperType> GeneralProduct<T> createProduct(
int type, UsedByProductThing<T> in) {
switch (type) {
case 1:
return (GeneralProduct<T>) new ProductA((UsedByProductThing<TypeA>) in);
// at this point, i want to return a "new ProductA(in)" preferably
// without casting
// or at least without the cast of the argument.
default:
throw new IllegalArgumentException("type unkown.");
}
}
}
如评论所述,我希望该工厂方法不使用强制转换。我知道返回类型必须是GeneralProduct,但我想不出省略强制转换的方式(它也给了我一个“未经检查的强制转换” - 警告)。而且,我想不出一种省略论证演员的方法。如果有必要摆脱那个地方的“不安全”铸造,我能够重组整个代码。你能告诉我一种在这里好看又顺畅的方法吗?
此外,请根据您的喜好编辑我的问题 - 我不知道如何在标题中正确解决问题。
非常感谢!
答案 0 :(得分:4)
你无法避免施放,因为
in
类型UsedByProductThing<T>
要转换为UsedByProductThing<TypeA>
且编译器无法知道T
是TypeA
GeneralProduct<TypeA>
,编辑器也不知道此处T
是TypeA
。避免强制转换的唯一方法是将T
替换为TypeA
public static GeneralProduct<TypeA> createProduct(
int type, UsedByProductThing<TypeA> in) {
switch (type) {
case 1:
return new ProductA(in);
default:
throw new IllegalArgumentException("type unkown.");
}
}
答案 1 :(得分:0)
我不确定有什么干净的方法可以做到这一点。此外,我认为任何投射你正在做的方式本质上都是不安全的,因为有人可以传递一个与“in”值不兼容的“类型”值。
话虽如此,在处理泛型时,这些固有的未经检查的演员阵容很常见。如果可能的话,你应该避免使用它们,但有时你不能,并且应该只添加注释来抑制你是否真的只想摆脱编译器警告。
@Suppress( “未登记”)
或者,为什么不采取建设者的方式?
public inteface Builder<T extends SuperType> {
public GeneralProduct<T> createProduct(UsedByProductThing<T> thing);
}
public class BuilderFactory {
public static <T extends SuperType> Builder<T> createBuilder(Class<T> clazz) {
if (clazz.equals(ProductA.class)) {
return new (Builder<T>) ProductABuilder();
}
...
}
}
然后使用它(假设您已经创建了一个构建器实现:
Builder<ProductA> builder = BuilderFactory.createBuilder(ProductA.class);
UsedByProductThing<ProductA> thing = ...;
ProductA product = builder.createProduct(thing);
答案 2 :(得分:0)
不要返回
"GeneralProduct<T>"
,更好的回归
"GeneralProduct<?>"
,所以不需要投射结果。
但无论如何,你必须为“ProductA”投射参数!