【问题标题】:Does java use ArrayList or LinkedList when you only specify that you are using a List interface?当您仅指定使用 List 接口时,java 是否使用 ArrayList 或 LinkedList?
【发布时间】:2014-02-11 21:56:24
【问题描述】:

我刚刚意识到我有一些代码可以运行并且所有测试都通过了,尽管我从未指定要使用 List 接口的哪个具体实现。

这是有问题的函数

public List<Product> getProductList(int CategoryId)
{
    List<Product> returnedProducts = null;
    HttpGet httpGet = new HttpGet("https://www.shirts.io/api/v1/products/category/"+CategoryId+"/?api_key="+this.apiKey);
    try
    {
        response = httpClient.execute(httpGet);
        if(response.getStatusLine().getStatusCode() == 200)
        {
            entity = response.getEntity();
            jsonResponse = EntityUtils.toString(entity);

            Type listType = new TypeToken<List<Product>>(){}.getType();
            JsonNode root = mapper.readTree(jsonResponse);
            ArrayNode products = (ArrayNode) root.path("result");
            returnedProducts = (List<Product>) gson.fromJson(products.toString(), listType);
        }

    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    return returnedProducts;
}

这是对上述功能的测试

public void testGetProductCategories()
{
    List<Category> categories = null;
    categories = productCalls.getProductCategories();
    assertEquals(20,categories.size());
}

一切正常,没有给我任何编译错误。为什么会这样?我认为您必须指定您使用的是 ArrayList 还是 LinkedList。为什么我的代码无需我指定其中一个即可运行?

【问题讨论】:

    标签: java arraylist linked-list


    【解决方案1】:

    当您返回gson.fromJson(products.toString(), listType); 的结果时,创建具体List 对象的责任在于gson

    【讨论】:

      【解决方案2】:

      因为fromJson 使用的是List 的哪个实现并不重要。您正在调用一个返回List 的方法——它正在创建某种List,但它是哪种实现并不重要。如果确实如此,那么它将返回一个ArrayList 或其他一些特定的实现。

      因为它返回List,所以有人可以更改fromJson 返回的List 的实现,而您的代码不必更改,因为它仍然是List,这就是所有需要的。

      【讨论】:

      • 在阅读了一些回复后,我得到 gson 只是返回一个 List 并且它以某种方式决定使用哪一个。但是现在我有了一个通用的 List 接口,我不是必须在我的所有代码中都使用“List”吗?如果我想使用特定的实现,我不能说 ArrayList myList = object.getProductList()。
      • 是的,您必须使用List,但这没有问题。你真的关心List 的哪个实现吗?如果您好奇,您可以随时使用returnedProducts.getClass().getName() 获取运行时类型,但看起来List 提供了您需要的所有功能。如果你想这样做,你也可以说new ArrayList&lt;Product&gt;(returnedProducts) 将返回的任何List 转换为ArrayList。但同样,这没有必要。
      【解决方案3】:

      在 Java 中,List 是一个接口。具体的List 实现(ArrayListLinkedList 或其他一些List)将由gson 选择,并且对您(作为调用者)不应该很重要。有兴趣的可以随时拨打getClass()这样的电话——

      if (categories != null) {
        System.out.println(categories.getClass().getName());
      }
      

      【讨论】:

        【解决方案4】:

        首先,由于ArrayListLinkedList 都实现了List,它们都是List 实例。

        在您看到对List 的引用的任何地方,它都可以引用ArrayListLinkedList,或任何其他实现。它被称为is an 关系。

        就像你的车,如果交通法规说“你的车”,不管是什么牌子,都是指它,因为铃木和大众都执行汽车的“契约”。

        通常,使用提供您需要的功能的更通用的接口/超类是一个很好的建议。这样,您可以只更改对象的实例化类,其他类也在相同的is an 关系中,其余代码无需更改。

        【讨论】:

        • 我知道他们都实现了 List 接口。但我认为您不能实例化接口,而是必须实例化实现该接口的类的对象。
        • 您不会从接口实例化对象,只能从非抽象类实例化,您是对的。最后,会有一个new ClassName()。但是您对实例的引用可以由类型为接口的变量处理:List myList&lt;String&gt; = new ArrayList&lt;String&gt;();
        猜你喜欢
        • 1970-01-01
        • 2014-11-07
        • 2010-09-24
        相关资源
        最近更新 更多