Tôi có một khai báo mảng như sau:
int a[];
Đây a
là một mảng kiểu nguyên thủy int
. Mảng này được lưu trữ ở đâu? Nó được lưu trữ trên heap hay stack? Đây là một kiểu primitve int
, tất cả các kiểu nguyên thủy không được lưu trữ trên heap.
Tôi có một khai báo mảng như sau:
int a[];
Đây a
là một mảng kiểu nguyên thủy int
. Mảng này được lưu trữ ở đâu? Nó được lưu trữ trên heap hay stack? Đây là một kiểu primitve int
, tất cả các kiểu nguyên thủy không được lưu trữ trên heap.
Câu trả lời:
Như gurukulki đã nói, nó được lưu trữ trên đống. Tuy nhiên, bài đăng của bạn gợi ý một sự hiểu lầm có thể là do một số người có thiện chí tuyên truyền huyền thoại rằng "những người nguyên thủy luôn sống trên chồng". Điều này là không đúng sự thật. Biến cục bộ có giá trị của chúng trên ngăn xếp, nhưng không phải tất cả các biến nguyên thủy đều là cục bộ ...
Ví dụ, hãy xem xét điều này:
public class Foo
{
int value;
}
...
public void someOtherMethod()
{
Foo f = new Foo();
...
}
Bây giờ, f.value
sống ở đâu? Huyền thoại cho rằng nó nằm trên ngăn xếp - nhưng thực ra nó là một phần của Foo
đối tượng mới và sống trên đống 1 . (Lưu ý rằng giá trị của f
chính nó là một tham chiếu và nằm trên ngăn xếp.)
Từ đó, đây là một bước dễ dàng để tạo mảng. Bạn có thể nghĩ về một mảng chỉ là rất nhiều biến - vì vậy new int[3]
cũng giống như việc có một lớp có dạng này:
public class ArrayInt3
{
public readonly int length = 3;
public int value0;
public int value1;
public int value2;
}
1 Trong thực tế, nó phức tạp hơn thế này. Sự phân biệt ngăn xếp / đống hầu hết là một chi tiết triển khai - tôi tin rằng một số JVM, có thể là những JVM thử nghiệm, có thể biết khi nào một đối tượng không bao giờ "thoát" khỏi một phương thức và có thể phân bổ toàn bộ đối tượng trên ngăn xếp. Tuy nhiên, về mặt khái niệm , nó nằm trên đống, nếu bạn chọn quan tâm.
String
được hỗ trợ bởi a char[]
. Tôi tin rằng các chuỗi ký tự được lưu trữ trong nhóm hằng số công khai; đối với tối ưu hóa GC, điều đó có nghĩa là các mảng hỗ trợ cũng phải được lưu trữ tương tự (nếu không thì nhóm hằng số sẽ phải được quét trong bất kỳ chu kỳ GC nào trong đó mảng hỗ trợ sẽ đủ điều kiện để thu thập).
Nó sẽ được lưu trữ trên heap
vì mảng là một đối tượng trong java.
CHỈNH SỬA : nếu bạn có
int [] testScores;
testScores = new int[4];
Hãy coi đoạn mã này giống như nói với trình biên dịch, "Tạo một đối tượng mảng sẽ chứa bốn giá trị nguyên và gán nó cho biến tham chiếu có tên testScores
. Ngoài ra, hãy tiếp tục và đặt từng int
phần tử thành 0. Cảm ơn."
-g
tùy chọn cho trình biên dịch. Nếu không nó sẽ được tối ưu hóa đi.
Nó là một mảng các kiểu nguyên thủy mà bản thân nó không phải là kiểu nguyên thủy. Một nguyên tắc nhỏ là khi từ khóa mới được tham gia, kết quả sẽ nằm trên đống.
Tôi chỉ muốn chia sẻ một vài bài kiểm tra tôi đã chạy về chủ đề này.
Mảng cỡ 10 triệu
public static void main(String[] args) {
memInfo();
double a[] = new double[10000000];
memInfo();
}
Đầu ra:
------------------------
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
------------------------
Như bạn thấy, kích thước heap đã sử dụng được tăng lên ~ 80 MB, là 10m * sizeof (gấp đôi).
Nhưng nếu chúng ta sử dụng Double thay vì double
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
memInfo();
}
Đầu ra sẽ hiển thị 40MB. Chúng tôi chỉ có tham chiếu Đôi, chúng không được khởi tạo.
Làm đầy nó với 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();
}
Vẫn là 40MB. Vì chúng đều trỏ đến cùng một đối tượng Double.
Khởi tạo với double thay thế
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
Hàng
a[i] = qq.doubleValue();
tương đương với
a[i] = Double.valueOf(qq.doubleValue());
tương đương với
a[i] = new Double(qq.doubleValue());
Vì chúng tôi tạo các đối tượng Đôi mới mỗi lần, chúng tôi sẽ thổi bay đống. Điều này cho thấy các giá trị bên trong lớp Double được lưu trữ trong heap.
Trong ngôn ngữ lập trình Java, mảng là các đối tượng, được tạo động và có thể được gán cho các biến kiểu Đối tượng.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html