【问题标题】:Why Java Generic can't design to inherit to a parent Generic class?为什么 Java Generic 不能设计为继承到父 Generic 类?
【发布时间】:2013-10-21 22:15:01
【问题描述】:

各位,我可能对 Java 中的 Generic 有一个基本的误解,

为什么我们不能写一个 Java Generic 子类来继承它的父 Generic 类?

定义如:

public class JsonResponse<T> implements Response {
}

但我定义了另一个子类来继承它:

public class MeetingClientResponse<T> extends JsonResponse<T> {
}

我将另一个调用者类定义为:

public interface HttpExecutor<T extends Response> {
}

实现它的类是:

public class DefaultHttpExecutor<T extends Response> implements HttpExecutor<T> {
       public DefaultHttpExecutor(ResponseHandler<T> responseHandler) {
    this.responseHandler = responseHandler;

}
}

public class JsonResponseHandler<T> implements ResponseHandler<JsonResponse<T>> {
}

public class ScheduleMeetingResponseHandler extends
    JsonResponseHandler<ScheduleMeetingResponseVO> {
}

handler = ScheduleMeetingResponseHandler.newIntance()

当我这样使用时,没有编译错误:

HttpExecutor<JsonResponse<ScheduleMeetingResponseVO>> httpExecutor = 
new DefaultHttpExecutor
         <JsonResponse<ScheduleMeetingResponseVO>>(handler);

但是当我这样使用时,它会在 Eclipse 中编译错误:

HttpExecutor<MeetingClientResponse<ScheduleMeetingResponseVO>> httpExecutor = 
new DefaultHttpExecutor
          <MeetingClientResponse<ScheduleMeetingResponseVO>>(handler);

Eclipse 提示错误为:构造函数 DefaultHttpExecutor 未定义

【问题讨论】:

  • 这两个声明都可以在 Eclipse 上正常编译。
  • 你得到什么错误信息?
  • 你能指定你在 Eclipse 中遇到的错误吗?
  • 构造函数 DefaultHttpExecutor 未定义
  • @JerryCai 如果只显示,应该为他们两个显示该错误。你的handler 是如何声明的?

标签: java generics inheritance


【解决方案1】:

DefaultHttpExecutor 构造函数声明为

public DefaultHttpExecutor(ResponseHandler<? super T> responseHandler)

这是因为您尝试为MeetingClientResponse 创建一个DefaultHttpExecutor,但您传递给它的是一个用于JsonResponse 的处理程序。

通过该声明,您声明执行程序将能够使用特定于 MeetingClientResponse 的处理程序,或者可以满足特定类型的超类型的更多通用处理程序。

另见What is PECS (Producer Extends Consumer Super)?

【讨论】:

    【解决方案2】:

    DefaultHttpExecutor&lt;T&gt; 构造函数需要一个 ResponseHandler&lt;T&gt; 参数。更准确地说,它期望参数声明ResponseHandler&lt;T&gt;。因此,您需要将处理程序声明ResponseHandler&lt;MeetingClientResponse&lt;ScheduleMeetingResponseVO&gt;&gt;(或子类型):

    ResponseHandler<MeetingClientResponse<ScheduleMeetingResponseVO>> handler;
    

    我强调了声明这个词,因为声明才是最重要的。如果你的处理程序被声明为ResponseHandler&lt;JsonResponse&lt;ScheduleMeetingResponseVO&gt;&gt;,你会得到一个编译错误,即使你的处理程序实际上是一个ResponseHandler&lt;MeetingClientResponse&lt;ScheduleMeetingResponseVO&gt;&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多