ฉันมีการประกาศอาร์เรย์ดังนี้:
int a[];
นี่a
คืออาร์เรย์ของint
ประเภทดั้งเดิม อาร์เรย์นี้เก็บไว้ที่ไหน? เก็บไว้ในฮีปหรือสแต็ก? นี่คือประเภทไพรม์ไทม์ชนิดint
ดั้งเดิมทั้งหมดจะไม่ถูกเก็บไว้ในฮีป
ฉันมีการประกาศอาร์เรย์ดังนี้:
int a[];
นี่a
คืออาร์เรย์ของint
ประเภทดั้งเดิม อาร์เรย์นี้เก็บไว้ที่ไหน? เก็บไว้ในฮีปหรือสแต็ก? นี่คือประเภทไพรม์ไทม์ชนิดint
ดั้งเดิมทั้งหมดจะไม่ถูกเก็บไว้ในฮีป
คำตอบ:
ตามที่ gurukulki กล่าวไว้มันถูกเก็บไว้ในกอง อย่างไรก็ตามโพสต์ของคุณแสดงให้เห็นถึงความเข้าใจผิดซึ่งอาจเกิดจากบุคคลที่มีเจตนาดีบางคนเผยแพร่ตำนานที่ว่า นี่ไม่เป็นความจริง ตัวแปรท้องถิ่นมีค่าในสแต็ก แต่ไม่ใช่ตัวแปรดั้งเดิมทั้งหมดที่เป็นโลคัล ...
ตัวอย่างเช่นพิจารณาสิ่งนี้:
public class Foo
{
int value;
}
...
public void someOtherMethod()
{
Foo f = new Foo();
...
}
ตอนนี้f.value
อาศัยอยู่ที่ไหน? ตำนานขอแนะนำให้มันอยู่ในสแต็ค - แต่จริง ๆ แล้วมันเป็นส่วนหนึ่งของใหม่Foo
วัตถุและชีวิตในกอง1 (โปรดทราบว่าค่าของf
ตัวมันเองเป็นข้อมูลอ้างอิงและอยู่ในสแต็ก)
จากนั้นเป็นขั้นตอนง่ายๆในการจัดเรียงอาร์เรย์ คุณสามารถคิดว่าอาร์เรย์เป็นเพียงตัวแปรจำนวนมากดังนั้นnew int[3]
ก็เหมือนกับการมีคลาสของรูปแบบนี้:
public class ArrayInt3
{
public readonly int length = 3;
public int value0;
public int value1;
public int value2;
}
1อันที่จริงมันซับซ้อนกว่านี้ ความแตกต่างของสแต็ก / ฮีปส่วนใหญ่เป็นรายละเอียดการใช้งาน - ฉันเชื่อว่า JVM บางตัวอาจเป็นแบบทดลองสามารถบอกได้ว่าเมื่อใดที่วัตถุไม่เคย "หลบหนี" จากเมธอดและอาจจัดสรรวัตถุทั้งหมดบนสแต็ก อย่างไรก็ตามมันเป็นแนวความคิดเกี่ยวกับกองถ้าคุณเลือกที่จะดูแล
String
ได้รับการสนับสนุนโดยไฟล์char[]
. ฉันเชื่อว่าสตริงตามตัวอักษรถูกเก็บไว้ในพูลคงที่สาธารณะ สำหรับการเพิ่มประสิทธิภาพ GC นั่นหมายความว่าควรจัดเก็บอาร์เรย์สำรองในลักษณะเดียวกัน (มิฉะนั้นจะต้องสแกนพูลคงที่ในระหว่างรอบ GC ใด ๆ ที่อาร์เรย์สำรองจะมีสิทธิ์ได้รับการรวบรวม)
มันจะถูกเก็บไว้ในฮีป
เนื่องจากอาร์เรย์เป็นวัตถุใน java
แก้ไข : ถ้าคุณมี
int [] testScores;
testScores = new int[4];
ให้คิดว่าโค้ดนี้พูดกับคอมไพเลอร์ว่า "สร้างออบเจ็กต์อาร์เรย์ที่จะเก็บ int สี่ตัวและกำหนดให้กับตัวแปรอ้างอิงที่ชื่อtestScores
นอกจากนี้ให้ตั้งค่าแต่ละint
องค์ประกอบเป็นศูนย์ขอบคุณ"
-g
ตัวเลือกให้กับคอมไพเลอร์ มิฉะนั้นจะถูกเพิ่มประสิทธิภาพออกไป
มันเป็นอาร์เรย์ของประเภทดั้งเดิมซึ่งในตัวมันเองไม่ได้เป็นแบบดั้งเดิม หลักการที่ดีคือเมื่อคีย์เวิร์ดใหม่เข้ามาเกี่ยวข้องผลลัพธ์จะอยู่ในฮีป
ฉันแค่อยากจะแบ่งปันการทดสอบบางอย่างที่ฉันทำในหัวข้อนี้
อาร์เรย์ขนาด 10 ล้าน
public static void main(String[] args) {
memInfo();
double a[] = new double[10000000];
memInfo();
}
เอาท์พุต:
------------------------
max mem = 130.0 MB
total mem = 85.0 MB
free mem = 83.6 MB
used mem = 1.4 MB
------------------------
------------------------
max mem = 130.0 MB
total mem = 130.0 MB
free mem = 48.9 MB
used mem = 81.1 MB
------------------------
ดังที่คุณเห็นขนาดฮีปที่ใช้เพิ่มขึ้น ~ 80 MB ซึ่งเป็น 10m * sizeof (double)
แต่ถ้าเราใช้ Double แทน double
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
memInfo();
}
เอาต์พุตจะแสดง 40MB เรามีเพียงการอ้างอิงสองครั้งเท่านั้นพวกเขาจะไม่เริ่มต้น
เติมด้วย Double
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq;
}
memInfo();
}
ยังคงเป็น 40MB. เพราะทั้งหมดชี้ไปที่วัตถุคู่เดียวกัน
เริ่มต้นด้วย double แทน
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq.doubleValue();
}
memInfo();
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
ไลน์
a[i] = qq.doubleValue();
เทียบเท่ากับ
a[i] = Double.valueOf(qq.doubleValue());
ซึ่งเทียบเท่ากับ
a[i] = new Double(qq.doubleValue());
เนื่องจากเราสร้างวัตถุคู่ใหม่ทุกครั้งเราจึงระเบิดฮีป ค่านี้แสดงค่าภายในคลาส Double จะถูกเก็บไว้ในฮีป
ในอาร์เรย์ของการเขียนโปรแกรมภาษา Java เป็นอ็อบเจ็กต์ซึ่งสร้างขึ้นแบบไดนามิกและอาจกำหนดให้กับตัวแปรชนิด Object
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html