다음과 같은 배열 선언이 있습니다.
int a[];
다음 a
은 기본 int
유형 의 배열입니다 . 이 어레이는 어디에 저장됩니까? 힙 또는 스택에 저장됩니까? 이것은 primitve 유형 int
이며 모든 기본 유형은 힙에 저장되지 않습니다.
다음과 같은 배열 선언이 있습니다.
int a[];
다음 a
은 기본 int
유형 의 배열입니다 . 이 어레이는 어디에 저장됩니까? 힙 또는 스택에 저장됩니까? 이것은 primitve 유형 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 일 수있는 일부 JVM은 객체가 메소드에서 "이스케이프"되지 않는시기를 알려주고 전체 객체를 스택에 할당 할 수 있습니다. 그러나 신경 쓰도록 선택하면 개념적 으로 힙에 있습니다.
String
a로 백업됩니다 char[]
. 나는 리터럴 문자열이 공개 상수 풀에 저장되어 있다고 믿습니다. GC 최적화의 경우 이는 백업 어레이도 마찬가지로 저장되어야 함을 의미합니다 (그렇지 않으면 백업 어레이가 수집에 적합한 GC주기 동안 상수 풀을 스캔해야 함).
힙에 저장됩니다.
배열은 자바의 객체이기 때문입니다.
편집 : 만약 당신이
int [] testScores;
testScores = new int[4];
이 코드는 컴파일러에게 "4 개의 정수를 담을 배열 객체를 만들고라는 참조 변수에 할당합니다 testScores
. 또한 각 int
요소를 0으로 설정 합니다. 감사합니다." 라고 말하는 것으로 생각 하세요 .
-g
컴파일러에 옵션을 제공하는 경우에만 코드에 "Thanks"라고 표시됩니다 . 그렇지 않으면 멀리 최적화됩니다.
그 자체로 원시가 아닌 원시 유형의 배열입니다. 경험상 좋은 규칙은 새 키워드가 관련 될 때 결과가 힙에 있다는 것입니다.
이 주제에 대해 실행 한 몇 가지 테스트를 공유하고 싶었습니다.
1000 만 크기의 배열
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
------------------------
보시다시피 사용 된 힙 크기는 10m * sizeof (double) 인 ~ 80MB만큼 증가합니다.
하지만 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 객체를 가리 키기 때문입니다.
대신 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 객체를 생성하기 때문에 힙을 날려 버립니다. Double 클래스 내의 값이 힙에 저장되어 있음을 보여줍니다.
Java 프로그래밍 언어에서 배열은 객체이고 동적으로 생성되며 Object 유형의 변수에 할당 될 수 있습니다.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html