Java泛型:要求泛型是特定类型的子类

6

我有一个抽象的泛型类:

public abstract class AbstractMessageHandler<T extends AbstractMessageHandler>
{
    public abstract List<String> getTypesOfMessages();
    public abstract void handleMessage(String message, CometClient client);

    public T setResponseValues(AbstractMessage request, T response )
    {
        response.setCompanyId(request.getCompanyId());
        response.setMessageGroup(request.getMessageGroup());
        response.setUserId(request.getUserId());
        response.setTimeStamp(AbstractMessage.getCurrentTimeStamp());

        return response;
    }
}

我希望泛型子类成为此类的子类。换句话说,泛型必须是AbstractMessageHandler的子类。然而,这会导致编译问题。有谁能告诉我我做错了什么吗?
谢谢

发布编译器错误。希望您真的只想要求一个通用子类TAbstractMessageHandler理论上实现的interface,我想这个interface的名称是MessageHandler。相关地,setResponseValues最有可能将其参数作为Message而不是AbstractMessage。除非没有它们实现的interface,否则这些要求是不必要的限制。 - pickypg
没有上下文的情况下,我会想象你的类型约束中的AbstractMessageHandler本身需要一个类型参数。你确定这是你问题的最佳设计吗?还是你的意思是 AbstractMessageHandler<T extends AbstractMessage>? - Jeremy Roman
3个回答

8

您需要遵循Enum类的示例:

public abstract class AbstractMessageHandler<T extends AbstractMessageHandler<T>>

我不同意。在他给出的代码中,我没有看到任何比 <T extends AbstractMessageHandler<?>> 更好的类型优势。无论如何,Enum 是一个特殊情况,因为 Enum 的子类是由语言创建的,并被强制使用与自身完全相同的泛型参数来继承 Enum。这在任何其他情况下都不成立。你不能在任何其他情况下强制执行这一点。 - newacct
@newacct - 实际上,你可以这样做。你试过了吗?这是一个非常方便的模式。我在我的代码中使用过,所以我知道它是有效的。 - jtahlborn
如果你有class Foo extends AbstractMessageHandler<Foo>{ ... },那么你可以有class Bar extends AbstractMessageHandler<Foo>{ ... }。那么这个限制到底起到了什么作用呢? - newacct
@newacct - 我不明白你的问题。你是在问如果你误用模式,为什么它还有用?误用模式并不会使其变得无用。通常情况下,在类层次结构的底部之前,您不会在绑定中使用具体类型。您只需在中间类上继续模式即可。显然,为绑定选择其他随机类并没有什么帮助... - jtahlborn
泛型的作用是提供可证明的保证,避免需要强制类型转换。这个递归边界防止了什么类型转换? - newacct
@newacct - 当正确使用时,它允许超类方法返回子类类型(对于构建器样式的类尤其有用)。请参见示例基本类型具体类型 - jtahlborn

0
在您的通用定义中,您可以使用<T extends SomeClass>
例如:
abstract class Processor<T extends String> {
    abstract T process();
}

在你的情况下,看起来 T 应该扩展某个 Response 类,而不是 AbstractMessageHandler

1
注意:他在第一行。他遇到了其他问题。 - pickypg
是的,当我写这个时,他加了那个。 - Reverend Gonzo

0
从给定的代码来看,似乎没有必要将类设计成泛型。那么考虑使用一个泛型方法替代(我甚至将其设计成静态方法,因为似乎你根本不需要使用当前对象):
public abstract class AbstractMessageHandler
{
    public static <T extends AbstractMessageHandler> T setResponseValues(AbstractMessage request, T response )
    {
        response.setCompanyId(request.getCompanyId());
        response.setMessageGroup(request.getMessageGroup());
        response.setUserId(request.getUserId());
        response.setTimeStamp(AbstractMessage.getCurrentTimeStamp());

        return response;
    }
}

甚至更好的方法是,在AbstractMessageHandler上定义一个操作当前对象的方法。这样,您就不需要这个静态方法,也不会有这个奇怪的参数,您总是返回它。
public abstract class AbstractMessageHandler
{
    public void setResponseValues(AbstractMessage request)
    {
        setCompanyId(request.getCompanyId());
        setMessageGroup(request.getMessageGroup());
        setUserId(request.getUserId());
        setTimeStamp(AbstractMessage.getCurrentTimeStamp());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接