为啥 Java Generic 不能设计为继承到父 Generic 类?

Posted

技术标签:

【中文标题】为啥 Java Generic 不能设计为继承到父 Generic 类?【英文标题】: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 是如何声明的? 【参考方案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;

【讨论】:

以上是关于为啥 Java Generic 不能设计为继承到父 Generic 类?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的继承关系,子类不需要写super关键字。也能调用到父类的方法么?

java学习--基础知识进阶第二天--笔记

java基础---继承

子类可以继承到父类上的注解吗

为啥构造函数在java中不被继承?

为啥不能在 Java 中扩展注解?