Java';s参考系统在多个容器中存储数据时是否有助于节省内存? 基本问题
考虑这个对象:Java';s参考系统在多个容器中存储数据时是否有助于节省内存? 基本问题,java,Java,考虑这个对象: Person alice = new Person("Alice", 0); 它被添加到两个ArrayList中: ArrayList<Person> foo = new ArrayList<Person>(); ArrayList<Person> bar = new ArrayList<Person>(); foo.add(alice); bar.add(alice); ArrayList foo=new
Person alice = new Person("Alice", 0);
它被添加到两个ArrayList中:
ArrayList<Person> foo = new ArrayList<Person>();
ArrayList<Person> bar = new ArrayList<Person>();
foo.add(alice);
bar.add(alice);
ArrayList foo=new ArrayList();
ArrayList条=新的ArrayList();
foo.add(alice);
加上(爱丽丝);
此时,堆内存中是否有三个Person对象(alice
每个ArrayList中加一个)?或者内存中是否有一个Person对象以及指向它的三个引用(指针)
提出/更复杂问题的动机
Person对象有两个字段,一个字符串和一个int。假设我有许多Person对象,我希望它们在不同的时间以两种不同的方式进行排序(有时按字符串的字母顺序,有时按int的数字顺序)
这似乎可以通过两种方式实现:
- 有一个容器,比如ArrayList,包含对象,每当我想更改排序方案时,根据需要对其进行排序
- 有两个容器,一个按字符串字母顺序排序,另一个按整数数字排序
在C++语言中,在时间和空间上高效地执行这一操作将需要第二种方式,但是多个容器指针指向单个对象的集合。因为这很困难,人们经常推荐这样的东西,这正是它的作用。在Java中,我看到了一些可能的事情,因为所有Java对象都在指针式引用后面
他们这样做对吗?在Java中,以节省空间的方式进行第二种操作是否与使用多个容器对相同对象进行冗余引用一样简单 奖金问题 在其他语言中,如JavaScript、Python、Ruby、C#、Go、Rust等,这是正确的还是错误的 此时,堆内存中是否有三个Person对象(alice加上每个ArrayList中的一个) 一个人
内存中的对象,带有三个对象引用(指针)。您声明的Person alice
变量包含一个引用,而您创建的每个列表包含一个对象引用(指针)的单个元素。所以一共有3篇参考文献
从技术上讲,ArrayList
是对象引用()的列表,而不是对象。当我们说ArrayList
时,我们指的是只允许指向类Person
对象的指针列表,但不允许指向School
或Invoice
。因此,个人
对象、学校
或发票
对象的大小与列表
中的大小无关。每个列表
中的元素在每个元素中仅包含一个对象引用,因此它们的大小始终相同
需要理解的棘手部分是,Java语法是特意设计来对Java程序员隐藏引用/指针的。这为我们在日常编程工作中方便地将列表
视为包含人
对象。我们知道底层结构实际上是引用/指针,但我们不需要考虑这一点
当我们从列表中检索人员时:
Person p = foo.get( 0 ) ; // Annoying zero-based index counting. So zero is the first element.
…Java的工作是访问列表中的元素,获取其存储的引用/指针,然后跟随该引用/指针查找该对象在内存中的位置,并返回该内存位置(基本上是一个数字),以存储在本例中名为p
的个人对象引用变量中
当我们从该Person
对象中获取名称成员时:
String name = p.name ;
…JVM遵循存储在p
中的引用/指针来定位内存中其他位置浮动的实际对象,然后在该内存块中移动以查找对象中的name
成员变量
相比之下,C语言使这些指针非常明显并且可用。这使得编程更加混乱和复杂,更容易出错
在开始编程时,您不需要了解所有这些。偶尔重温一下这个话题,仔细考虑一下,最终它会变得有意义。图表可以提供帮助。有关更多信息和图纸,请参阅我对相关问题的回答,以及。搜索堆栈溢出,因为此主题已被多次介绍,如和
分类
使用,您有两个选项可以按排序顺序访问一组对象:在切换顺序时重新排序,或维护两个集合。对象中内容的大小无关紧要,因为集合中只涉及指针
当然,第三方可以自由开发自己的集合来展示其他行为。对于Java、C#和JavaScript来说,有两种“类型”——原语和对象。原语存储在堆栈中,因此作为堆栈中存储点表示的变量具有原语的值。对象存储在堆中,所有变量只存储对它们的引用(请注意,引用与指针有点不同,但您可以将它们视为无法操作的隐藏指针)。所有数据都是通过值传递的——原语和引用(C#ref和out关键字除外)。因此,是的,数组保存对这些对象的引用,而不是对象本身。Java和JavaScript不允许您存储原语和对堆栈的直接引用以外的任何内容,而C#具有与C/C++中的结构相似的结构,但它们的使用并不多。此外,C#还有指针,这些指针现在或至少永远不应该被使用。Python处理内存的方式有点不同,它对待所有内存都像