Java集合:对象直接添加到集合中吗?

3

我知道当我向一些集合(如LinkedList)添加对象时,实际上并不是将元素直接添加到集合中,而是向集合中添加一个节点来提供链接功能,这个节点有一个引用指向我添加到集合中的对象。所有Java集合类都是这样吗?例如,当我执行以下操作时:

List<String> list = new ArrayList<String>();
list.add("Car");

字符串对象"Car"是直接添加到列表中,还是只添加指向"Car"的节点到列表中?

此外,我能认为这是代理设计模式吗?


ArrayList 将添加的 String 直接存储在内部使用的数组中。 - MrSmith42
4
@MrSmith42:不是这样的。因为String是引用类型,ArrayList在其内部数组中存储对String的引用。事实上,像ArrayList这样的集合只能存储引用对象,并且总是以这种方式进行。 - Hovercraft Full Of Eels
1
@Hovercraft Full Of Eels:这就是我的意思(当然,字符串并没有被复制)。引用没有被包装在额外的对象中,比如一个节点。 - MrSmith42
它是直接存储还是其他方式存储有什么区别呢?Java中的每个对象都是引用分配和引用的,除了堆栈类型(如int、char和其他基本类型)。 - Aniket Inge
@Hovercraft Full Of Eels:我理解问题的方式是:是否有像Node对象一样的包装器?而与'SrrayList'相关的答案是NO。顺便提一下,在LinkedListNode中也有对添加对象的引用。 - MrSmith42
显示剩余3条评论
3个回答

5
Java中的ArrayList使用数组来存储对象的引用,因此与代理模式无关。您可以自己查看,这里是指向其OpenJDK实现的链接。第103行有相关的代码片段。
private transient Object[] elementData;

你还可以将其与使用节点存储对下一个和上一个元素的引用的 LinkedList进行比较,后者是在List中。

谢谢Peter。在LinkedList的情况下,你认为这是一个代理模式吗?在这种情况下,添加的元素被包装在一个Node中,然后添加到LinkedList中?我不确定代理模式还是装饰器模式更适合这种情况。 - user1888243
实际上,原始值并没有存储在ArrayList或任何集合中。您只能存储对象。Java将原始类型转换为其对象等效项(int-> Integer,float-> Float等),然后可以将其存储在集合中。 - chubbsondubs

2
不,将元素添加到LinkedList中不是代理模式。代理模式是一种创建模式。LinkedList中包含的内容并没有发生创造。节点包装对象并不足以使其成为代理。包装节点也没有与其和集合中包含的对象实现共享接口。
代理是一个可以代替另一个对象的对象,因此共享接口很重要。这个代替对象可以通过按需创建真实对象来节省内存、时间或两者兼而有之。它还可以选择在不需要时销毁该对象。代理控制其所包装的对象的生命周期,这是代理模式的一个标志。集合中的节点并不控制其指向的对象的生命周期,因为它被赋予了包装的对象。
例如,假设我们有一个连接到多个数据库的应用程序,但它并不总是需要同时连接所有数据库。我们可以实现一个特殊的DataSource,在请求连接时仅创建基础DataSource。当您没有活动连接时(例如,当最后一个连接关闭时),它还可以关闭DataSource。这类似于大多数连接池库中实现连接池的方式。基础DataSource只提供连接到数据库,但连接池是在DataSource之上进行分层的,并提供了连接池,客户端无需意识到正在发生。

1
你实际上可以查看ArrayList等的源代码。
ArrayList在内部使用Object[]数组,因此不涉及额外的包装器,但它直接存储对象引用。所以这里绝对没有“代理”。
如果输入基本类型,它们将被自动装箱为对象。我也不会称其为代理模式的实例。
如果你寻找代理模式,请看一下RMI。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接