[Java] 참조 자료형
자바에서는 8개의 기본 자료형 이외의 모든 자료형은 참조 자료형이다. 대표적인 참조 자료형에는 Array, Class, Interface 등이 있다.
배열
- 배열은 동일한 자료형을 묶어 저장하는 참조 자료형
- 특징
1. 생성할 때 크기를 지정해야 한다.
2. 한 번 크기를 지정하면 절대 변경할 수 없다.
배열을 선언하면 스택 메모리에 변수의 공간만 생성하고, 아직 배열의 실제 데이터인 객체를 생성하지 않았기 때문에 공간 안은 비운 채로 둔다. 스택 메모리에 위치하고 있는 참조 자료형 변수의 빈 공간을 초기화할 때는 null값을 사용할 수 있다. null 값은 힙 메모리의 위치를 가리키지 않는 것으로 연결된 실제 데이터가 없다는 것을 의미한다.
자바의 메모리 구조
클래스 영역 정적 영역 상수 영역 메서드 영역 |
스택 영역 | 힙 영역 |
첫 번째 영역에는 클래스와 메서드가 위치하고 있으며, 스택 영역은 기본 자료형이든, 참조 자료형이든 상관없이 모든 지역 변수가 위치하고 있는 영역이다. 마지막으로 힙 영역은 객체가 위치하는 공간이며, 객체는 참조 자료형 변수가 가리키는 실제 데이터이다.
배열 생성하기
1. 배열 선언하기
자료형[] 변수명 자료형 변수명[]
int[] a; int a[];
double[] b; double b[];
String[] c; String c[]
2. 힙 메모리에 배열의 객체 생성하기
모든 참조 자료형의 실제 데이터(객체)는 힙 메모리에 생성된다. 힙 메모리에 객체를 생성하기 위해서는 new키워드를 사용해야 한다.
배열의 객체 생성
new 자료형[배열의 길이]
new int[3];
new String[5];
3. 배열 자료형 변수에 객체 대입하기
3-1. 변수 선언과 값(참조 자료형은 객체)의 대입을 한 번에 작성
int[] a = new int[3];
3-2. 변수 선언과 값 따로 작성
int[] a;
a = new int[3];
-> a는 참조 변수로 실제 데이터값을 저장하는 것이 아니라 실제 데이터값의 위치값을 저장
4. 객체에 값 입력하기
참조 변수명[인덱스] = 값;
int[] = new int[3];
a[0] = 3;
a[1] = 4;
a[2] = 5;
-> 인덱스는 0부터 시작하며 1씩 증가한다
배열 생성시 선언과 객체 대입 분리시 주의할 점
int[] a = new int[]{3, 4, 5}; // ( O )
int[] a;
a = new int[]{3, 4, 5}; // ( O )
int[] a = {3, 4, 5}; // ( O )
int[] a;
a = {3, 4, 5}; // ( X )
기본 자료형과 참조 자료형의 초기값
→ int a = 0; int[] b = null;
스택 메모리값은 강제 초기화 X
int value1;
// System.out.println(value1); 오류
int[] value2;
// System.out.println(value2); 오류
-> 스택 메모리에 위치하는 변수는 초기화 없이 출력 불가능
기본 자료형 VS 참조 자료형
- 기본 자료형: 스택 메모리에 실제 데이터값을 저장하고 있으므로 기본 자료형 변수를 복사하면 실제 데이터값이 1개가 더 복사된다. 이후 복사된 값을 아무리 바꿔도 원본값은 아무런 영향을 받지 않는다.
int a = 3;
int b = a;
b = 7;
-> a: 3, b: 7
- 참조 자료형: 스택 메모리에 실제 데이터값이 아닌 힙 메모리에 저장된 객체의 위치를 저장하고 있다. 따라서 참조 자료형 변수를 복사하면 실제 데이터가 복사되는 것이 아니라 실제 데이터의 위치값이 복사된다. 따라서 하나의 참조 변수를 이용해 데이터를 수정하면 다른 참조변수가 가리키는 데이터도 변하게 된다.
int[] a = {3, 4, 5,};
int[] b = a;
b[0] = 7;
-> a[0]: 7, b[0]: 7
String 클래스
특징
1) 한 번 정의된 문자열은 변경할 수 없다.
· 객체 안의 값을 변경하면 새로운 객체를 생성
· String str1 = new String("안녕")과 같은 형태로 작성하면 "안녕"은 힙 메모리에 생성되며, 생성된 실제 데이터의
위치값이 스택메모리의 str1 공간에 저장
· String str2 = str1, 즉 참조 자료형의 값을 복사하면 스택 메모리의 값이 복사되므로 str1과 str2는 모두 동일한
객체를 가리킴
· str1 = "안녕하세요"와 같이 수정하면 기존의 문자열을 수정하는 것이 아닌 "안녕하세요"라는 문자열을 포함하고
있는 새로운 String 객체를 생성하고 이 위치를 str1의 공간에 저장
2) 문자열 리터럴을 바로 입력해 객체를 생성할 때 같은 문자열끼리 객체를 공유
· new로 생성할 때는 동일한 문자열 객체가 힙 메모리에 있든 없든 무조건 새롭게 객체를 생성
· 문자열 리터럴로 생성할 때는 힙 메모리에 리터럴로 생성된 동일 문자열을 포함하고 있는 객체가 있으면 그 객체를
공유
ex)
String a = new String("안녕");
String b = "안녕";
String c = "안녕";
String d = new String("안녕");
System.out.println(a == b); // false
System.out.println(b == c); // true
System.out.println(c == d); // false
System.out.println(d == a); // false
equals()
두 문자열의 위치값이 아닌 실제 데이터값을 비교하며, 이 때 대소문자를 다 비교한다.
→ stack 메모리 비교(==): 위치 비교, equals(): 내용 비교