关于 Java 中数组的引用

huangapple go评论89阅读模式
英文:

About reference to array in Java

问题

《Core Java Volume I》一书中的示例:

public class Employee {
    ...
}
public class Manager extends Employee {
    ...
}
Manager[] managers = new Manager[3];
Employee[] staff = managers; //OK
staff[0] = new Employee(); //error

staff[0]会导致 ArrayStoreException 异常,因为数组存储了错误的对象。我给出了数组的内存示意图:

关于 Java 中数组的引用

我认为变量 staff 存储了 staff[0] 的地址(类似于 C++,在 int *p = new int[3] 中,变量 p 存储了数组的第一个元素的地址)。

因为 staff 等于 managers,所以它们指向内存的相同位置,当你执行语句 staff[0] = new Employee() 时,我认为这等同于语句 managers[0] = new Employee(),将父类的引用指向子类对象是错误的。

我不太确定自己是否正确,我希望了解关于数组引用(staff/managers)和单个数组元素(staff[0]staff[1] 等)之间的关系,以及 staff 是否可以告诉我数组中第一个元素的内存位置。

我还想知道,对于不同的对象数组,比如 Cat[] cats = new Cat[2]Dog[] dogs = new Dog[2],它们在内存中是否占用相同大小。引用不同对象是否占用相同的内存量?

英文:

A example in book 《Core Java Volume I》

public class Employee {
    ...
}
public class Manager extends Employee {
    ...
}
Manager[] managers = new Manager[3];
Employee[] staff = managers; //OK
staff[0] = new Employee(); //error

staff[0]will cause ArrayStoreException, beacuse the array store a wrong object.
I give the memory diagram of the array:
关于 Java 中数组的引用
I think variable staff store the address of staff[0](like c++, where in int *p = new int[3], variable p stores the address of the first element of the array).

Because staff is equal to managers, so they point to the same position of memory, when you write the statement staff[0] = new Employee(), I think it is equal to the statement managers[0] = new Employee(), the reference to parent points to the child object is wrong.

I'm not sure if I'm right, I hope to know the relationship of the reference to array (staff/managers) and the individual array elements (staff[0], staff[1]...), whether staff can tell me the position in memory of the first element in array.

And I would also like to know, for different arrays of objects, like Cat[] cats = new Cat[2] and Dog[] dogs = new Dog[2], whether they take up the same size in memory. Do references to different objects take up the same amount of memory?

答案1

得分: 2

在Java中,个别的数组元素是数组对象内的变量,如语言规范中的第10节所述。从语言层面来看,没有内存地址或指针运算。语言不会告诉您staff[0]staff[1]的内存地址与staff之间是否有任何关系 - 这留给了实现来决定。

至于实现的工作方式,Aleksey Shipilёv(JOL的原始作者)的这篇文章是一个很好的资源:https://shipilev.net/jvm/objects-inside-out/

总之,数组对象的内存布局包括指向对象类的指针,帮助进行垃圾收集和并发的“标记字”,数组的长度(项目数量),以及数组元素本身。

由于“对象头”的存在,staff[0]不位于与staff相同的地址上。但是这种差异是JVM已知的数字,因此它可以生成使用“推测”的高效代码来访问数组元素。

至于ArrayStoreException是如何抛出的:当您创建一个对象数组,比如new Manager[3]时,JVM会设置类指针,以便引用“Manager数组”类(如果不存在,则会动态创建)。当您将对象引用存储到数组中时,JVM使用这个类指针来检查引用是否与数组组件类型兼容,如果不兼容,则抛出ArrayStoreException

英文:

> I hope to know the relationship of the reference to array (staff/managers) and the individual array elements (staff[0], staff[1]...), whether staff can tell me the position in memory of the first element in array.

In Java, the individual array elements are variables within the array object, as described in section 10 in the language specification. On the language level, there are no memory addresses or pointer arithmetic. The language does not tell you if there is any relation between the memory addresses of staff[0] and staff[1] and staff - that is left up to the implementation.

As for how the implementation works, this article from Aleksey Shipilёv (the original author of JOL) is a great resource: https://shipilev.net/jvm/objects-inside-out/

In summary, the array object memory layout includes a pointer to the object's class, a "mark word" that helps with garbage collection and concurrency, the array's length (number of items), followed by the array elements themselves.

Because of the "object header", staff[0] is not at the same address as staff. But the difference is a number known to the JVM, so it can generate efficient code that uses dead reckoning to access array elements.

As for how the ArrayStoreException gets thrown: When you create an array of objects such as new Manager[3], the JVM sets the class pointer so it references the "array of Managers" class (if one doesn't already exist, it's created on the fly). When you store an object reference to the array, the JVM uses this class pointer to check whether the reference is compatible with the array component type, and throws ArrayStoreException if it's not.

huangapple
  • 本文由 发表于 2020年8月14日 21:55:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63414179.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定