【问题标题】:Java List is an interface with implemented methods? [closed]Java List 是具有实现方法的接口? [关闭]
【发布时间】:2015-02-01 22:51:33
【问题描述】:

Java 列表(也是集合)有方法实现(add(),get())那么它们怎么可能是接口呢? 我希望:

List <Integer> nums = ArrayList <Integer>();
nums.add(5);  

上面的代码会出错,因为 add() 应该在 ArrayList 而不是 List(作为接口)中实现但事实并非如此,代码工作正常。 有人可以解释一下吗?

【问题讨论】:

  • "列表(也是集合)有方法实现(add(),get()"你能告诉我们吗(顺便说一句,声明!= 实现)?此外,由于 Java 8 接口可以有一些 default methods 但在 List add()get() 不是其中之一。
  • 您似乎对接口到底是什么感到困惑。
  • List 没有实现。否则你可以写 List nums = List ();而是(这不起作用)。
  • @DuKes0mE 由于 Java 8 List 几乎没有像sort(Comparator) 这样的实现方法,所以我们不再需要使用Collections.sort(list,Comparator),但由于它仍然只是接口,它可能有其他未实现的方法,所以我们仍然无法通过new List初始化它。

标签: java list arraylist interface implements


【解决方案1】:

这只是多态的作用。 ArrayList 是一个List,因此可以分配给List 类型的变量。

接口定义了实现它的任何类的契约。它没有实现方法(警告:这在 Java 8 中有所改变)。

变量numsList,但由于赋值,它的具体类型是ArrayList。运行时将其视为多态,因此运行时动态绑定到存储在nums 中的实际类型上的add:即它调用ArrayList 上的add 方法。

我建议阅读The Java Tutorials > Polymorphism,以及同一部分中有关接口的页面。

【讨论】:

    【解决方案2】:

    接口是一种契约,它背后肯定有一些具体的实现。例如,您可以使用

    List<Integer> nums = ArrayList<>(); 
    

    List<Integer> nums = LinkedList<>(); 
    

    它们在内部实现方面有所不同(但ArrayListLinkedList 都满足List 接口指定的合同)。最后,在 Java 8+ 中,interface(s) 可以有 default methods

    【讨论】:

      【解决方案3】:

      implements List 承诺该类具有在接口List 中声明的所有方法。如果您需要的对象只是 List 方法,那么它实际上是哪个类并不重要,只要该类实现了 List

      List nums = new ArrayList (); 声明 numsList 引用。这意味着它所指向的任何对象都必须是实现List 的类的实例,因此具有List 声明的所有方法。

      nums.add(5); 使用add 方法,任何对象nums 引用都必须提供,因为它必须实现List

      【讨论】:

        【解决方案4】:

        对于interface 是什么,或者至少是如何使用它们,您似乎有些困惑。 Java 中的interface 定义了一组方法签名,implements 接口必须提供的任何类(否则为abstract)。 ArrayList 就是这样一个实现List 接口的类。当您执行以下操作时:

        List<Integer> nums = ArrayList<Integer> ()
        

        您正在创建一个ArrayList 的实例,它实现了List 的所有方法,并将它分配给一个变量,该变量可以保存任何实现List 的对象。这意味着在使用nums 时,您只能访问List 公开的方法。然而,真正被调用的方法是ArrayList的方法。

        Java 鼓励使用interfaces,因为它们没有绑定到特定的继承链。考虑以下方法签名:

        public <T> void foo(List<T> input)
        public <T> void bar(ArrayList<T> input)
        

        foo 方法可以采用任何实现List 的东西;这可以是标准库对象之一,例如ArrayListLinkedList,或者它可以是用户定义的类,除了标准的List 操作之外还提供完全不同的功能。这使它更加灵活; foo 只是声明需要一个看起来和行为都像 List 的对象,但并不关心该对象是什么。

        另一方面,bar 方法直接使用ArrayList。如果稍后你意识到你想使用不同的集合,你会被卡住,因为你只能使用 ArrayList 或扩展 ArrayList 的类。

        【讨论】:

          【解决方案5】:

          如您所见(OpenJDK 源代码):http://www.docjar.com/html/api/java/util/List.java.html

          List 是 no 实现的接口。您需要声明一个 ArrayList 或另一个实现此接口的 List

          【讨论】:

          • 您无需查看源代码即可看到。 Javadc 告诉你。
          • @EJP 这是真的。我不确定 OP 在什么时候声称 List 有一个实际的实现。
          【解决方案6】:

          你应该学习继承。 List 是一个不包含任何实现的接口。但是 ArrayList 包含了 List 接口的所有实现。

          当您调用 nums.add(5) 时,您会看到正在调用 List.add() 方法,但实际上它在后台调用 ArrayList.add(5) 方法。这就是继承的秘密

          检查这个:http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

          【讨论】:

            【解决方案7】:

            方法体是根据引用持有的对象的实际类型(称为late or dynamic binding)动态(在运行时)加载的,因此对于代码

            List <Integer> nums = ArrayList <Integer>();
            

            nums 引用中的实际对象将是ArrayList 类的实例,因此add/get 的代码将从ArrayList 加载。

            List 实际上并没有实现get() 方法,而是调用了

            nums.add(5);  
            

            这对编译器来说不是问题,因为它知道ArrayList 将包含来自List 接口的所有抽象(无主体)方法的一些实现。

            【讨论】:

              猜你喜欢
              • 2016-08-17
              • 2015-10-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-25
              • 1970-01-01
              相关资源
              最近更新 更多