1. 참조 타입
Last updated
Last updated
기본 타입(primitive type
)
스택 영역에 그 자체를 저장
정수, 실수, 문자, 논리, 리터럴
참조 타입(reference type
)
객체의 번지를 참조하는 타입
스택 영역에 참조변수만 저장
실제 내용은 힙 영역에 저장
배열, 열거, 클래스, 인터페이스
변수와 내용이 스택 영역에 저장된다.
참조변수는 스택영역에 저장되어 힙 메모리의 주소를 저장한다.
실제 참조변수가 가리키는 내용은 힙메모리에 저장된다.
JVM은 운영체제에서 Runtime Data Area
메모리 영역을 할당받아 다음과 같이 세부 영역으로 구분해서 사용한다.
배열과 객체를 저장하는 영역이다.
이 영역에서 생성된 배열과 객체의 주소를 참조 변수가 갖고 있다.
생성된 배열, 객체를 참조화는 참조 변수가 사라지면 생성되었던 해당 힙 영역은 JVM Garbage Collector에 의해 제거된다
JVM 스택 영역은 각 쓰레드마다 하나씩 할당된다.
쓰레드를 만들지 않으면 1개의 main
쓰레드만 존재하며, JVM 스택 영역도 1개이다.
메소드 호출 시마다 프레임을 추가(push
)하고 메소드가 종료되면 해당 프레임을 제거(pop
)한다.
예외 발생 시에 printStackTrace()
메소드는 이 스택 영역을 기준으로 프레임을 출력한다.
프레임 내부에 로컬 변수 스택이 존재한다.
변수도 추가(push
) 되고 제거(pop
) 된다.
변수에 최초로 값이 저장되어 초기화될 때, 추가(push
)된다.
변수는 선언된 블록 안에서만 스택에 존재하고, 블록을 벗어나면 스택에서 제거된다.
if문 블록 안에 어떤 변수가 있다면, if문이 끝나면 해당 변수는 로컬 변수 스택에서 빠져(pop
)나간다.
기본 타입 변수의 ==
, !=
연산은 값이 같은지 다른지 확인한다.
참조 타입 변수의 ==
, !=
연산읜 참조하는 주소의 값이 같은지 다른지 확인한다.
내용이 같은지는 확인하지 않는다.
참조 타입 변수가 힙 영역의 주소를 참조하지 않으면, null
을 갖는다.
null
을 갖는 참조 타입 변수도 초기화되었다고 생각하기 때문에 스택 영역에 올라간다.
null
을 가진 참조 타입 변수를 이용하려고 하면, NullPointerException
이 발생한다.
String
은 참조 타입 변수다.
같은 리터럴을 저장하는 참조 타입 변수는 같은 힙의 주소를 참조한다.
단, new String()
과 같이 새로운 객체를 생성한 경우에는 다른 주소를 참조한다.
String
끼리의 내용을 비교할 때는 .equals()
메소드를 쓰는게 정확하다.
같은 타입의 많은 데이터를 다룰 때 사용한다.
다른 타입을 저장하려고 하면 타입 불일치(Type mismatch) 컴파일 오류가 발생한다.
한 번 생성된 배열은 길이를 늘리거나 줄일 수 없다.
타입 옆에 대괄호([]
)나 변수명 옆에 대괄호([]
) 어느 방식으로도 가능하다.
배열 역시 참조 변수에 속하므로 null
을 참조하여 초기화될 수 있다.
위 코드 중
a
의 경우가 특별한데, 배열 생성 후 즉시 초기화 할 때만 문법에서new int[]
가 생략된다고 이해하면 쉽다.
정수형 기본 타입
byte[]
: 0
char[]
: \u0000
short[]
: 0
int[]
: 0
long[]
: 0L
실수형 기본 타입
float[]
: 0.0F
double[]
: 0.0
논리형 기본 타입
boolean[]
: false
참조 타입
클래스[]
: null
인터페이스[]
: null
배열변수.length
다차원 배열은 앞의 숫자에 계속해서 뒤의 숫자만큼 자식 트리로 뻗어나간 공간이 생긴다고 생각하면 쉽다.
위는 2
개의 트리에 3
개의 자식트리가 각각 달리니 2*3
만큼의 공간이 생긴다.
다차원 배열은 수학 행렬구조가 아니라 계단식 구조도 가질 수 있다.
위 코드에서 stair[0]
에는 2
개의 공간이 연결된 반면에 stair[1]
에는 3
개의 공간이 연결되어 있다.
시각화해보면 정사각형이 아닌 계단형이다.
배열이 객체를 참조하면, 배열 객체가 힙 영역에 생긴다.
힙 영역에 생긴 배열 객체 내부에서는 배열의 주소마다 힙 영역에 있는 다른 객체를 참조하는 형태가 된다.
배열은 한번 생성하면 크기를 변경할 수 없기 때문에, 더 큰 배열을 만들어 이전의 배열을 복사하는 일이 꽤 있다.
System.arraycopy()
메소드를 이용해 주로 복사한다.
참조 타입의 배열을 복사하면, 참조 주소를 그대로 복사하기 때문에 참조하는 원본의 주소는 같다.
위와 같은 복사를 얕은 복사(shallow copy)라 한다.
참조하는 객체도 별도로 생성하는 것은 깊은 복사(deep copy)라고 한다.
기존의 for
문 처럼 카운터 변수(i
)와 증감식(i++
)을 사용하지 않는 형태이다.
한정된 값만을 갖는 타입을 열거 타입이라 한다.
열거 타입은 몇 개의 열거 상수(enumeration constant) 중에서 하나의 상수를 저장하는 데이터 타입이다.
열거 타입의 이름은 일반적 관례상 첫 글자를 대문자로 한다.
열거 타입에 들어가는 상수들은 모든 문자를 대문자로 한다.
여러 단어가 들어가는 경우 언더바(_
)로 구분한다.
ex) MONDAY_MORNING
, LOGIN_SUCCESS
일반적인 클래스의 타입을 선언하듯 선언하고, 사용하면 된다.
해당 변수는 힙 영역에 있는 열거타입 상수를 참조하게 된다.
name()
메소드
열거 객체가 가지고 있는 문자열을 리턴한다.
ordinal()
메소드
열거 객체 중 몇 번째 열거 객체인지 알려준다.
compareTo()
메소드
매개값으로 주어진 열거 객체를 기준으로 전후 몇번째 위치하는지를 반환한다.
values()
메소드
열거 타입의 모든 열거 객체들을 배열로 만들어 리턴한다.