</ p>的差异super / extends String&gt;在方法和变量声明 [英] Difference for &lt;? super/extends String&gt; in method and variable declaration

查看:154
本文介绍了</ p>的差异super / extends String&gt;在方法和变量声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

再次,当准备我自己参加OCJP考试时,我偶然发现一个问题,我既不能解释自己也不能找到解释。这是:



Givin:

  import java.util。 *; 

public class Hancock {
// insert code here
list.add(foo);
}
}

在第5行独立插入的两个代码片段,将编译没有警告? (选择两个)

  A。 public void addString(List list){
B. public void addString(List< String> list){
C. public void addString(List<?super String> list){
D. public void addString(List< ;? extends String> list){

正确的答案是B& C。



答案A和B对我来说很清楚。对于答案C&我知道继承的方式,但我不能理解为什么回答D不编译在Eclipse中,而所有其他人做的(一个关于通用,B& C没有warrings)。



在Eclipse中为错误答案D是方法add(capture#1-of?extends String)类型List< capture#1-of? extends String>不适用于参数(String)



另一方面,它编译:

  public void addString(){
List< ;? extends String> list1 = new ArrayList< String>();
List< ;? super String> list2 = new ArrayList< String>();
}

为什么?为什么< ;?



我知道 String / code>是最终类,不能被任何其他类扩展,但是不能解释这里发生了什么。

解决方案<首先,让我们看看答案C:

  public void addString(List< ;? super String> list){
list.add(foo);
}

此方法声明表示您将允许传递 List String 的某个超类进行参数化的对象,例如 String Object 。所以:


  1. 如果您通过 List< String> > $
  2. 如果您通过 List< Object> list.add(foo)将是完全有效的,因为foo是 String 您可以向列表<对象> )添加 String



      这意味着答案C是正确的。






      回答D。



      如果你有这样的方法声明:

        public void addString(List< ;? extends String> list){

      }

      这意味着您将能够传递由 String 某个未知子类型参数化的列表 $ c>。所以,当你做 list.add(foo); 时,编译器不会知道提供的对象是否具有匹配 unknown < String 的子类型,因此引发了编译时错误。






      当您有:

        public void addString(){
      List< ;? extends String> list1 = new ArrayList< String>();
      List< ;? super String> list2 = new ArrayList< String>();
      }

      这个片段编译正常,因为 list1 定义为保存 String 的某个未知子类型的 List 对象,包括 String 本身,这就是为什么它是有效的。
      问题是将无法添加任何,除了 null



      对于 list2 ,变量可以保存由一些超类型参数化的 List 对象 String ,包括 String 本身。






      更多信息:




      again, while preparing myself for OCJP exam i stumbled upon a question that i can neither explain to myself nor find an explanation. Here it is:

      Givin:

      import java.util.*;
      
      public class Hancock {
          //insert code here
              list.add("foo");
          }
      }
      

      Which two code fragments, inserted independently at line 5, will compile without warnings? (Choose two)

      A. public void addString(List list) {
      B. public void addString(List<String> list) {
      C. public void addString(List<? super String> list) {
      D. public void addString(List<? extends String> list) {
      

      Correct answers are B & C.

      Answers A and B are quite clear for me. For the answers C & D i know which way the inheritence is going, however i cannot understand why answer D does not compile in Eclipse while all others do (A with warrning about generic, B & C without warrings).

      Error in Eclipse for answer D is The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String).

      On the other hand this compiles:

      public void addString() {
          List<? extends String> list1 = new ArrayList<String>();
          List<? super String> list2 = new ArrayList<String>();
      }
      

      Why? Why <? super String> does not compile in method declaration while it does compile in variable declaration.

      I know that String is final class and cannot be extended by any other class but that does not explain to me what is going on here.

      解决方案

      First, let's see answer C:

      public void addString(List<? super String> list) {
          list.add("foo");
      }
      

      This method declaration says that you will be allowed to pass List objects which are parametrized by some super class of String, for example String or Object. So:

      1. If you pass List<String> the list.add("foo") will be perfectly valid.
      2. If you pass List<Object> the list.add("foo") will be perfectly valid, because "foo" is a String (and you can add a String to a List<Object>).

      This means that answer C is correct.


      Lets now see answer D.

      If you have a method declaration like this:

      public void addString(List<? extends String> list) {
      
      }
      

      this means that you will be able to pass List objects parametrized by some unknown subtype of String. So, when you do list.add("foo"); the compiler won't be aware if the provided object has a type that matches the unknown subtype of String and therefore raises a compile-time error.


      When you have:

      public void addString() {
          List<? extends String> list1 = new ArrayList<String>();
          List<? super String> list2 = new ArrayList<String>();
      }
      

      This fragment compiles fine, because list1 is defined to hold List objects that are of some unknown subtype of String, including the String itself, which is why it's valid. The problem is that you won't be able to add anything, except null.

      As for list2, the variable can hold List objects which are parametrized by some super-type of String, including the String itself.


      More info:

      这篇关于</ p>的差异super / extends String&gt;在方法和变量声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆