【问题标题】:Why is declaring List implementation not needed? [duplicate]为什么不需要声明 List 实现? [复制]
【发布时间】:2015-06-26 21:31:40
【问题描述】:

我正在使用返回类型 List<> 的方法,然后我可以在该 List 上调用方法:

List<Artist> artists = artistsPager.artists.items;
artists.add(new Artist());

要明确artistsPager.artists.items 是返回类型List&lt;Artist&gt;

既然List 只是一个接口,编译器怎么让我使用这个artists 对象,List&lt;&gt; 不是总是需要一个实现,比如ArrayList

例如,编译器不会让我执行以下操作,因为“列表是抽象的;无法实例化”:

List<Integer> list = new List<Integer>();

artistsPager.artists.itemsnew List&lt;Integer&gt;() 有何不同?

对于那些好奇的人,这来自Java Web API wrapper for Android。非常感谢所有帮助。

我不相信这是question 的重复,因为即使答案相同,但引发他们的问题却不同。另一个问题是问ListArrayList 类型之间的区别,而我的问题是想知道为什么当List 的实现被隐藏时编译器没有抱怨。

我可以将其标记为重复项以将未来用户引导至该问题,但我认为不应该关闭它,因为我认为这里的答案对其他用户非常有帮助。

【问题讨论】:

  • 您应该查找接口/抽象类,看看它们是如何在 Java 中使用的。这是一套重要的知识,尤其是在处理像 Android 和 JDK 这样的高配置库时,因为接口几乎在它们的任何地方都使用。
  • 感谢@DaveLugg,我很困惑,因为我查看了 Spotify API 的源代码,除了类型 List 之外找不到任何它的实例化。下次我会相信编译器!有没有什么快速的方法可以找出 List 的实际实现位置,而不是遍历代码?
  • 使用接口的重点是你不应该关心它在哪里实现,只要它是一个ListArrayList 类型是它的一个实现,并且可能是最常见的。所以你可以使用List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();。您可以在 oracle 文档 (docs.oracle.com/javase/6/docs/api/java/util/List.html) 中找到 List 接口的默认实现,并查看“所有已知的实现类”
  • 知道了,感谢@DaveLugg 的帮助。

标签: java list interface spotify


【解决方案1】:

artistsPager.artists.items 与 new List&lt;Integer&gt;() 有何不同?

artistsPager.artists.itemsList&lt;&gt; 类型的字段。在代码中的某处,它一定是用ArrayList 之类的具体实现实例化的。

new List&lt;Integer&gt;()是构造函数调用,由于List是接口,所以无效。

【讨论】:

  • 知道了,我想我是糊涂了,因为我没有看到 List 类型的具体实现。
【解决方案2】:

List&lt;&gt; 不是总是需要一个实现,比如ArrayList&lt;&gt;

是的,您需要实现才能创建实例。但是,编译器知道两件事:

  • 它知道你已经创建了一些实例,并将其分配给items,并且
  • 它知道你分配给items的任何东西都会实现List&lt;&gt;接口

知道这两件事就足以让编译器让您在声明为接口类型的变量上调用add。通过这种方式您的代码不需要关心您得到什么实现 - ArrayList&lt;&gt;LinkedList&lt;&gt; 或您开发的一些自定义实现:您的代码将适用于所有这些。 p>

请注意,通过接口类型引用对象的做法是可取的。它被称为接口编程。它使您可以隐藏实现细节,并在以后为不同的实现交换对象。

【讨论】:

    【解决方案3】:

    这意味着在某处创建了一个具体列表(例如,ArrayList)。

    你只知道创建的列表是从List接口实现的方法,允许你使用这些方法。

    以这个例子为例,对用户隐藏具体的LinkedList

    public static List<Integer> makeListOfInts(){
        return new LinkedList<Integer>(){
            {
                add(1);
                add(2);
            }
        }
    }
    

    我可以很容易地被ArrayList替换:

    public static List<Integer> makeListOfInts(){
        return new ArrayList<Integer>(){
            {
                add(1);
                add(2);
            }
        }
    }
    

    函数的用户只知道返回了List,但它不知道列表的具体类型。它只能使用来自List 接口的函数,而不是来自所选特定实现的函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      相关资源
      最近更新 更多