为什么不需要声明 List 实现?
Why is declaring List implementation not needed?
我正在使用 returns 类型 List<>
的方法,然后我可以调用 List
上的方法:
List<Artist> artists = artistsPager.artists.items;
artists.add(new Artist());
要明确 artistsPager.artists.items
返回类型 List<Artist>
。
因为 List
只是一个接口,编译器如何让我使用这个 artists
对象,List<>
不是总是需要一个实现,比如 ArrayList
?
例如,编译器不会让我执行以下操作,因为 "List is abstract; cannot be instantiated":
List<Integer> list = new List<Integer>();
artistsPager.artists.items
与 new List<Integer>()
有何不同?
对于那些好奇的人,这来自 Java Web API wrapper for Android。非常感谢所有帮助。
我不认为这是与此 question 的重复,因为即使答案相同,产生它们的问题也不同。另一个问题是询问类型 List
和 ArrayList
之间的区别,而我的问题是想知道为什么编译器在 List
的实现被隐藏时没有抱怨。
我同意将此标记为重复项以引导未来用户解决该问题,但我认为不应将其关闭,因为我认为此处的答案对其他用户非常有帮助。
How is artistsPager.artists.items any different than new List<Integer>()
?
artistsPager.artists.items
是 List<>
类型的字段。在代码的某处,它一定是用 ArrayList
.
这样的具体实现实例化的
new List<Integer>()
是构造函数调用,无效,因为List
是接口。
这意味着在某处创建了具体列表(例如,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
接口的函数,而不是来自所选特定实现的函数。
doesn't a List<>
always need an implementation, like ArrayList<>
?
是的,您需要一个实现才能创建一个实例。但是,编译器知道两件事:
- 它知道你已经创建了一些实例,并分配给
items
,并且
- 它知道您分配给
items
的任何内容都实现了 List<>
接口
知道这两件事足以让编译器让您对声明为接口类型的变量调用 add
。通过这种方式,您的 代码不需要关心您获得的是什么实现 - ArrayList<>
、LinkedList<>
或您开发的一些自定义实现:您的代码将工作与他们所有人。
请注意,通过接口类型引用对象的做法是可取的。它被称为编程到接口。它允许您隐藏实现细节,并在以后为不同的实现交换对象。
我正在使用 returns 类型 List<>
的方法,然后我可以调用 List
上的方法:
List<Artist> artists = artistsPager.artists.items;
artists.add(new Artist());
要明确 artistsPager.artists.items
返回类型 List<Artist>
。
因为 List
只是一个接口,编译器如何让我使用这个 artists
对象,List<>
不是总是需要一个实现,比如 ArrayList
?
例如,编译器不会让我执行以下操作,因为 "List is abstract; cannot be instantiated":
List<Integer> list = new List<Integer>();
artistsPager.artists.items
与 new List<Integer>()
有何不同?
对于那些好奇的人,这来自 Java Web API wrapper for Android。非常感谢所有帮助。
我不认为这是与此 question 的重复,因为即使答案相同,产生它们的问题也不同。另一个问题是询问类型 List
和 ArrayList
之间的区别,而我的问题是想知道为什么编译器在 List
的实现被隐藏时没有抱怨。
我同意将此标记为重复项以引导未来用户解决该问题,但我认为不应将其关闭,因为我认为此处的答案对其他用户非常有帮助。
How is artistsPager.artists.items any different than
new List<Integer>()
?
artistsPager.artists.items
是 List<>
类型的字段。在代码的某处,它一定是用 ArrayList
.
new List<Integer>()
是构造函数调用,无效,因为List
是接口。
这意味着在某处创建了具体列表(例如,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
接口的函数,而不是来自所选特定实现的函数。
doesn't a
List<>
always need an implementation, likeArrayList<>
?
是的,您需要一个实现才能创建一个实例。但是,编译器知道两件事:
- 它知道你已经创建了一些实例,并分配给
items
,并且 - 它知道您分配给
items
的任何内容都实现了List<>
接口
知道这两件事足以让编译器让您对声明为接口类型的变量调用 add
。通过这种方式,您的 代码不需要关心您获得的是什么实现 - ArrayList<>
、LinkedList<>
或您开发的一些自定义实现:您的代码将工作与他们所有人。
请注意,通过接口类型引用对象的做法是可取的。它被称为编程到接口。它允许您隐藏实现细节,并在以后为不同的实现交换对象。