Java 如何为静态工厂方法定义泛型超类型?
如果已经有人问过这个问题,请链接并关闭这个问题 我目前正在为一个简化的API设计原型,这个API是另一个API中的一个,它要复杂得多,使用起来有潜在的危险 考虑到相关的有点复杂的对象创建,我决定使用静态工厂方法来简化API,目前我有以下方法可以按预期工作:Java 如何为静态工厂方法定义泛型超类型?,java,generics,Java,Generics,如果已经有人问过这个问题,请链接并关闭这个问题 我目前正在为一个简化的API设计原型,这个API是另一个API中的一个,它要复杂得多,使用起来有潜在的危险 考虑到相关的有点复杂的对象创建,我决定使用静态工厂方法来简化API,目前我有以下方法可以按预期工作: public class Glue<T> { private List<Type<T>> types; private Glue() { types = new ArrayList<
public class Glue<T> {
private List<Type<T>> types;
private Glue() { types = new ArrayList<Type<T>>(); }
private static class Type<T> {
private T value;
/* some other properties, omitted for simplicity */
public Type(T value) { this.value = value; }
}
public static <T> Glue<T> glueFactory(String name, T first, T second) {
Glue<T> g = new Glue<T>();
Type<T> firstType = new Glue.Type<T>(first);
Type<T> secondType = new Glue.Type<T>(second);
g.types.add(firstType);
g.types.add(secondType);
/* omitted complex stuff */
return g;
}
}
如前所述,这是预期的效果。当API用户=另一个开发人员键入Glue strongGlue=Glue.glueFactory2HP,new Horse,new Horse;他得到了他想要的东西
我所缺少的是,我如何强制实现这匹马——或者放入工厂方法中的任何东西——始终实现可序列化和可比较?使用简单地将它们添加到工厂方法的签名并不一定在所有情况下都强制执行此规则,仅当使用此简化API时。这就是为什么我想将它们添加到类的定义中,然后相应地修改工厂方法
附言:没有马,绝对没有小马!我想唯一合适的解决方案是,消除使用您提到的第二个API的可能性,并将您描述的类型约束添加到上面的静态工厂方法中
如果您不能反对第二个API,那么就不能强制执行此类约束。当然,您可以将适当的接口实现添加到类中,但第二个API不需要它,因此始终会有一个漏洞,错误可能会从中溜走。除了非REFED的泛型类型边界外,如果您需要,您还可以执行运行时检查,即
if (first instanceof Comparable && first instanceof Serializable) {
// everything's fine...
} else {
throw new IllegalArgumentException("what are you doing?");
}
你真的很接近。这是我的解决办法
public class Glue<T extends Serializable & Comparable<T>> {
private List<Type<T>> types;
private Glue() { types = new ArrayList<Type<T>>(); }
private static class Type<T> {
private T value;
/* some other properties, omitted for simplicity */
public Type(T value) { this.value = value; }
}
public static <V extends Serializable & Comparable<V>> Glue<V> glueFactory(
String name, V first, V second) {
Glue<V> g = new Glue<V>();
Type<V> firstType = new Glue.Type<V>(first);
Type<V> secondType = new Glue.Type<V>(second);
g.types.add(firstType);
g.types.add(secondType);
/* omitted complex stuff */
return g;
}
}
public class Horse implements Serializable, Comparable<Horse> {
private static final long serialVersionUID = 1156763996034008367L;
@Override
public int compareTo(Horse o) {
return 0;
}
}
public class Cat { }
public static void main(String[] args) {
Glue<Horse> gh = Glue.glueFactory("2HP", new Horse(), new Horse());
Glue<Cat> gc = Glue.glueFactory("2C", new Cat(), new Cat()); // <--- Does not compile, as requested!!
}
此程序在以下方面与您的代码不同:
我将glueFactory方法的类型参数T重命名为V。由于该方法是静态的,因此它的类型参数与包含的类类型参数没有关系,因此当这两个类型参数具有不同的名称时,代码更加清晰。
我添加了可序列化和可比较的边界。。。对V和T的声明
正如预期的那样,生成的程序编译Glue.glueFactory2HP,new Horse,new Horse;但拒绝胶水。胶水工厂2C,新猫,新猫 啊,我应该像你那样把T和V解耦。现在似乎工作正常。谢谢是的,不幸的是,在这一点上,反对是不可能的。这个简化的API的目的是向新朋友隐藏恐惧,让顽固的老朋友拥有他们复杂的API和所有奇怪的东西。