【问题标题】:Trouble in exam earlier today - ArrayList methods今天早些时候考试的麻烦 - ArrayList 方法
【发布时间】:2012-03-29 05:15:31
【问题描述】:

我今天早些时候参加了名为“Java for Android I”的课程的考试,发现了这个我没有得到的问题。也许你们中的一些人可以为我解释一下。

问题:

查看此集合ArrayList p。一个类 Person 是一个 学生的超类。 ArrayList 实现 List 接口 (根据 Java-API)。

编译器不允许出现代码中提到的某些情况。为什么? 描述它们如何可能导致 p 不包含 Person 的实例 或者为什么 p 不是 ArrayList 。例如。 p.add("Hello"); 现在 包含一个 String 实例。

代码:

p = new ArrayList<Object>();

void method ( ArrayList<Student> als) { ... }

void method ( List<Person> lp ) { ... }

void method ( ArrayList<Object> alo) { ... }

你会如何描述这个问题?我只是不明白我的教授想让我回答什么。

对不起,如果引用的语法搞砸了。我是从瑞典语翻译过来的。

【问题讨论】:

  • 这是问题的完整代码吗??
  • p 与方法声明有什么关系?
  • 我猜有些东西在翻译中丢失了...
  • 我同意,这听起来很混乱。
  • 如果他想知道为什么你可以/不能将变量 p 传递给所示的方法,这是有道理的。这就是@YuRDeD 在他的回答中的意思

标签: java android list collections arraylist


【解决方案1】:

虽然没有完全理解你的问题

第一种方法和第三种方法是根据 Java 过载规则的重复方法。编译器会说它们是重复的方法。

【讨论】:

    【解决方案2】:

    很难从您提供的内容中确定,但似乎教授可能会尝试测试您对泛型的一些微妙之处的理解。

    他没有显示引用 p 的声明这一事实是一个线索。

    如果通过引用 p 是合法的:

    method(ArrayList alo) //因为类型和参数 完全匹配

    这些是非法的:

    method(ArrayList<Student> als) //because the method will expect Student and will get Object
    method(List<Person>) //same reason.. expects list of Person, and will get Objects
    

    【讨论】:

    • 你可能是对的,我想我现在明白了。还是觉得题写的很烂。谢谢老哥的帮助! :)
    【解决方案3】:

    您的教授的问题是关于 Java 泛型中类型检查的基础知识。假设:

    class Person {
    }
    
    class Student extends Person {
    }
    

    这是一个有效的 sn-p:

    List<Person> list = new ArrayList<Person>();
    

    是这样的:

    List<Object> list = new ArrayList<Object>();
    

    这显然是无效的,因为对象可以是 Person 实例而不是 Student 实例:

    List<Student> list = new ArrayList<Person>();
    

    但是这个是我最喜欢的——它总是让人绊倒:

    List<Person> list = new ArrayList<Student>();
    

    这是一个无效的 sn-p。 “什么为什么!”我听到你问。好吧,确实所有Student 对象也是Person 的实例,所以像这样的分配工作:

    Person person = new Student();
    

    不过,当涉及到参数类型时,Java 编译器会尽力保护您。想象一下这段代码:

    List<Person> list = new ArrayList<Student>();
    
    list.add(new Person());
    

    如果编译器不反对分配,现在可以将Person 对象输入到仅托管Student 对象的ArrayList...

    方法调用的工作方式完全相同。只需从方法签名中去除参数的类型,然后尝试想象对该类型的赋值...

    【讨论】:

      【解决方案4】:

      或者它可能是关于以下 - 我不确定:)

      // take some method
      void method ( ArrayList<Object> ) { /* ... */ }
      
      // and an Object
      ArrayList<Object> p = new ArrayList<Object>();
      

      现在你可以说method(p),它会起作用,因为方法需要ArrayList&lt;Object&gt;。但是

      ArrayList<Student> q = new ArrayList<Student>();
      method ( q );
      

      不会工作。因为ArrayList&lt;Student&gt; 不是ArrayList&lt;Object&gt;,尽管Studend extends Object。要允许您必须定义方法:

      void method ( ArrayList<? extends Object> ) { /* ... */ }
      // or shorter but the same
      void method ( ArrayList<?> ) { /* ... */ }
      

      如果您想要一个可以同时采用 ArrayList&lt;Person&gt;ArrayList&lt;Student&gt;(以及 Person 的所有其他子类)的方法,您必须声明它

      void method ( ArrayList<? extends Person>) { /* ... */ }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多