我刚刚意识到我已经运行了一些代码并且所有测试都通过了,即使我从未指定要使用的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。为什么我的代码在没有指定一个或另一个的情况下运行?
答案 0 :(得分:4)
当您返回gson.fromJson(products.toString(), listType);
的结果时,创建具体List
对象的责任在于gson
。
答案 1 :(得分:2)
因为List
正在使用fromJson
的哪个实现并不重要。您正在调用一个返回List
的方法 - 它正在创建某种List
,但它与哪个实现无关。如果确实如此,那么它将返回ArrayList
或其他一些特定实现。
因为它返回List
,有人可以更改List
返回的fromJson
的实现,并且您的代码不必更改,因为它仍然是List
这就是所需要的。
答案 2 :(得分:2)
在Java中,List
是一个接口。具体的List实现(ArrayList
或LinkedList
或其他List
)将由gson选择,并且对您(作为调用者)不应该很重要。如果您很好奇,可以随时拨打getClass()
-
if (categories != null) {
System.out.println(categories.getClass().getName());
}
答案 3 :(得分:0)
首先,由于ArrayList
和LinkedList
都实现List
,因此它们都是List
个实例。
在任何地方,您都会看到对List
的引用,它可以引用ArrayList
或LinkedList
或任何其他实现。它被称为is an
关系。
就像你的车一样,如果交通法律谈到“你的车”,它就指的是它的品牌,因为铃木或大众汽车都实施了汽车的“合同”。
通常,使用提供所需功能的更通用的接口/超类是一个好建议。这样,您可以在同一个is an
关系中更改其他类的对象的实例化类,并且其余代码也不需要更改。