Java List是一个实现方法的接口?

时间:2015-02-01 22:51:34

标签: java list arraylist interface implements

Java Lists(也是Collection)有方法实现(add()get()),那么它们如何成为INTERFACES? 我希望:

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

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

7 个答案:

答案 0 :(得分:2)

这只是行动中的多态性。 ArrayList是一个List,因此可以分配给List类型的变量。

接口定义了实现它的任何类的契约。它没有实现这些方法(需要注意的是:从Java 8开始,这种情况正在发生变化)。

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

我建议在同一部分阅读The Java Tutorials > Polymorphism和接口页面。

答案 1 :(得分:1)

您似乎对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的类。

答案 2 :(得分:1)

接口是一个契约,并且保证它背后有一些具体的实现。例如,您可以使用

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

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

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

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

列表是一个具有实现的界面。您需要声明一个ArrayList或另一个实现此接口的List

答案 5 :(得分:0)

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

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

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

答案 6 :(得分:0)

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

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

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

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

nums.add(5);  

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