如果我们考虑下面的两个实现,那么第一个实际使用的是什么?
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
根据我在帖子中看到的内容,第一个实现有助于避免破坏更改,就像我们可以再次更改实现一样
a=new TreeList<String>();
但是我不明白为什么我们只能使用List接口方法来实际使用更改treelist的实现?
答案 0 :(得分:2)
但是我不明白为什么我们只能使用List接口方法来实际使用更改treelist的实现?
接口List
的不同实现对于不同的操作具有不同的性能特征。您应该选择哪种List
实现不是任意的 - 不同的实现对于不同的目的更有效。
例如,在ArrayList
上将元素插入中间的位置是昂贵的,但LinkedList
上的元素很便宜,因为实现的工作方式。同样,通过索引访问元素在ArrayList
上很便宜,但在LinkedList
上却很贵。
当您开始编写程序时,您可能会使用ArrayList
而不考虑太多,但稍后您会发现LinkedList
会更有效。
当你针对界面List
进行编程而不是特定的实现时,很容易从ArrayList
更改为LinkedList
- 到程序的其余部分,它仍然看起来就像List
一样,所以你只需改变一行。
答案 1 :(得分:1)
TreeList
不存在,因此我们以PersistentList
为例。
假设您有一个@Entity
要保存到数据库:
public class MyMagicEntity {
@OneToMany
List<MyChildEntity> children;
public void setChildren(final List<MyChildEntity> children) {
this.children = children;
}
}
现在,当您创建MyMagicEntity
时,您会执行类似
final MyMagicEntity mme = new MyMagicEntity();
final List<MyChildEntity> children = new ArrayList<>();
children.add(new MyChildEntity("one"));
children.add(new MyChildEntity("two"));
children.add(new MyChildEntity("three"));
mme.setChildren(children);
//save to DB
因此,您创建了一个ArrayList
,并将其传递到MyMagicEntity
,并将其分配给List
- 它并不关心底层实现是否只要它是List
{1}}。
现在,稍后你会这样做:
final MyMagicEntity mme = //load from DB
final List<Children> children = mme.getChildren();
那么,children
是什么?好吧,如果我们使用JPA和Hibernate,它实际上是PersistentList
,而不是ArrayList
。
当我们访问children
的成员时,Hibernate将从数据库中取出它们。此List
仍然是List
- 您的程序不必知道任何此类内容。
您可以在不使用List
界面的情况下执行此操作吗?没有!这是因为:
PersistentList
ArrayList
虽然这是一个极端的例子,List
的基本行为完全不同,但这适用于各种其他情况。
例如:
ArrayList
和LinkedList
具有不同的性能特征,您可能需要切换ImmutableList
您可能想要使用Collections.unmodifyableList
也implements List
,您可能想要使用List
由文件支持基本思想是List
定义任何列表必须能够执行的操作,而不是如何完成。
答案 2 :(得分:1)
让我们假设你已经决定开发一个更有效的List实现。也许内部具有更好的内存管理,或者可能是更快的设置方法(插入)实现。您可以实现List接口,其余代码将继续工作而不做任何更改,除了这一行。您还可以扩展ArrayList并编写自己的代码。
//Old code
List<String> a = new ArrayList<String>();
a.set(0, "Test");
//New code
List<String> a = new MyCustomisedList<String>();
//Same code, but your optimized set logic. May be faster...
a.set(0, "Test");
答案 3 :(得分:0)
此处List
是一个接口,其中包含可以使用List
执行的所有常用操作方法。
List
接口是ArrayList
,LinkedList
的父级,还有更多类。因此,它可以保存所有这些类型的Object引用。
所有这些List
方法都有不同的(或自己的类型)实现与不同的类。因此,无论您使用何种方法,都会根据属于该类的Object的覆盖方法定义自动应用。
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
现在,在你的情况下,你可以声明两种方式都没问题。但是假设像这样的情景。
您正在调用某些服务,并且您知道返回任何List
类型(非特定)的Object。它可能是LinkedList
或ArrayList
或任何其他类型的列表。
当时您得到的任何回复您可以轻松地将这些回复保存在List
参考变量类型中。
收集结果后,您可以进一步区分对象类型。