Java 确保子类是超类的泛型类型的实例
我正在创建一个JavaUtils库,遇到了泛型的问题。我已经找到了一个让库工作的解决方案,但它看起来像是糟糕的代码实践,并且容易出现未被检测到的程序故障。出于问题的考虑,我已经将程序简化为一个最小可验证的示例 假设我有一个接口Java 确保子类是超类的泛型类型的实例,java,generics,inheritance,Java,Generics,Inheritance,我正在创建一个JavaUtils库,遇到了泛型的问题。我已经找到了一个让库工作的解决方案,但它看起来像是糟糕的代码实践,并且容易出现未被检测到的程序故障。出于问题的考虑,我已经将程序简化为一个最小可验证的示例 假设我有一个接口可调用,它被调用以实现E public interface Invokable<E> { void invoke(E e); } 如果您创建一个新的PrintingInvokableUser()并在其上调用开始(),它将创建一个新的Printing
可调用
,它被调用以实现E
public interface Invokable<E> {
void invoke(E e);
}
如果您创建一个新的PrintingInvokableUser()
并在其上调用开始()
,它将创建一个新的PrintingInvokable()
并在其上调用调用(this)
,然后将打印出PrintingInvokableUser
的方法
虽然我的代码确实可以做到这一点,但这取决于一个不成文的期望,即InvokableUser
的子类Foo
将扩展InvokableUser
,涉及一个不检查的强制转换,这是错误的(并引发编译器警告),似乎甚至没有使用泛型类型,因为我可以用非泛型类型实现相同的效果,而且通常似乎必须有更好的方法来实现这一点
如果有人能为我指明正确的方向,我将不胜感激。谢谢 不可能避免在(E)上得到警告。这是一个众所周知的问题。有一个(不满意的)解决方案叫做“getThis技巧”,你可以用谷歌搜索。我猜这是一个抽象的E方法,子类应该从中返回this
?你猜对了。就我个人而言,我认为这是一个完全无用的解决方案,因为你必须在每一个类中重写它。是的,它似乎是编译器非强制要求和烦人的代码编写之间的选择。我想我必须在javadocs中非常明确地说明这个需求:p@Phoenix:“我猜这是一个抽象的E方法,子类应该从中返回这个”不需要返回这个
。它返回一个类型为E
(甚至可能与当前类的类型不同)的值。您可以在E
与类的类型相同的情况下实现类,并且可以返回this
。处于相同情况的其他人可以返回该类的其他实例。或者其他人可以拥有与类不同的E
,然后他们将返回该类型的实例。不管怎样,它是类型安全的。
public interface InvokableFactory<E> {
Invokable<E> create();
}
public class InvokableUser<E> {
private InvokableFactory<E> factory;
public InvokableUser(InvokableFactory<E> factory) {
this.factory = factory;
}
public void start() {
factory.create().invoke((E) this);
}
}
public class PrintingInvokable implements Invokable<PrintingInvokableUser> {
@Override
public void invoke(PrintingInvokableUser e) {
System.out.println(e.getString());
}
}
public class PrintingInvokableUser extends InvokableUser<PrintingInvokableUser> {
public PrintingInvokableUser() {
super(PrintingInvokable::new);
}
public String getString() {
return "( ͡° ͜ʖ ͡°)";
}
}