Home  >  Q&A  >  body text

java中在哪些情况下需要使用泛型通配符如:? extends T 或者 ? super T

至于什么是泛型通配符,我是知道的,但是不知道具体在项目里的使用场景,比如哪些情况下,我们创建的类或者接口需要用到泛型通配符呢

迷茫迷茫2763 days ago784

reply all(2)I'll reply

  • 阿神

    阿神2017-04-18 10:51:24

    Remember this sentence from the book Effective Java: Producer Extends, Consumer Super.
    It’s explained in detail here: http://stackoverflow.com/ques...

    Supplement

    TreeMaphas a constructor:

    public TreeMap(Comparator<? super K> comparator);
    

    You can think about why you need to specify the type Comparator<? super K> instead of Comparator<K> or Comparator<? extends K>?

    reply
    0
  • PHPz

    PHPz2017-04-18 10:51:24

    I don’t write Java, but all generics are interlinked. I happened to be looking at Taobao OPEN's SDK at this time. This is a real example that best explains generic wildcards.

    I specially found a Java version of SDK, see: https://github.com/ggd543/tao...

    -- url: https://github.com/ggd543/taobao-sdk-java/blob/master/src/main/java/com/taobao/api/TaobaoClient.java
    /**
         * 执行TOP公开API请求。
         * @param <T>
         * @param request 具体的TOP请求
         * @return
         * @throws ApiException
         */
    public <T extends TaobaoResponse> T execute(TaobaoRequest<T> request) throws ApiException ;

    All API requests are made through subclasses of execute 来操作的,而这个方法就采用的 ? extends T 通配符上界,来限制返回的对象必须是 TaobaoResponse.

    To put it simply, it is a constraint.

    From the perspective of Taobao SDK, the greatest value of the wildcard upper bound is that the results returned by all Taobao SDK requests will have a codemsg and other common parameters to indicate the request status of the API.

    Okay, let’s go back and look at the specific implementation of execute:

    if(this.needCheckRequest==true){
        try{
            request.check();//if check failed,will throw ApiRuleException.
        }catch(ApiRuleException e){
            T localResponse=null;
            try {
                localResponse=request.getResponseClass().newInstance();
            } catch (InstantiationException e2) {
                throw new ApiException(e2);
            } catch (IllegalAccessException e3) {
                throw new ApiException(e3);
            }
            localResponse.setErrorCode(e.getErrCode());
            localResponse.setMsg(e.getErrMsg());
            //localResponse.setBody("this.");
            return localResponse;
        }
    }

    Notice the subclass of catch 体中 localResponse,他的类型 T,但这个T并不是简单的一个Object对象,由于前面已经限定 T 的类型必须是 TaobaoResponse here.

    That means, when the definition of T 进行实例后,其类型至少是 TaobaoResponse 的子类,而对于 TaobaoResponse is this:

    --  url: https://github.com/ggd543/taobao-sdk-java/blob/master/src/main/java/com/taobao/api/TaobaoResponse.java
    
    public abstract class TaobaoResponse implements Serializable {
    
        private static final long serialVersionUID = 5014379068811962022L;
    
        @ApiField("code")
        private String errorCode;
    
        @ApiField("msg")
        private String msg;
    
        // more
    }

    So you can directly see code like this:

    localResponse.setErrorCode(e.getErrCode());

    Look, isn’t it interesting? All common parameters can be processed uniformly.

    So from the perspective of Taobao SDK, this is the meaning of generic wildcards.

    reply
    0
  • Cancelreply