✅ 원시 타입(Primitive Type)
: 정수, 실수, 문자, 논리 리터럴 등의 실제 데이터 값을 저장하는 타입
-
boolean, char, byte, short, int, long, float, double 8가지
-
스택(Stack) 메모리에 저장 됨
-
boolean
- true 또는 false를 저장
- Java의 최소 데이터 단위인 1Byte를 사용
-
char
- 기본적으로 1Byte를 사용하나, 한글이나 일본어등 동양권 언어에는 Unicode를 사용하므로 2 Byte를 사용
- Java에서 유일한 Unsigned(음수 값이 존재하지 않음) 데이터 형태
-
byte, short, int, long
- 정수형 데이터 타입
- byte, short, int의 경우 4 Byte단위로 저장되며, long은 8 Byte
- Java에서 long 사용 시 접미사 L을 붙여 long 타입임을 명시해줌
-
float, double
- 실수형 데이터 타입
- 실수형의 기본 데이터 타입은 double로 float을 사용할 경우 접미사 F를 명시
- float는 4 Byte, double은 8 Byte 사이즈 단위로 저장
✅ 참조 타입(Reference Type)
- 객체의 주소를 참조하는 타입으로, 메모리 번지 값을 통해 객체를 참조하는 타입
- Java에서 Primitive Type을 제외한 타입들이 모두 Reference 타입이며, java.lang.Object 클래스를 상속하는 모든 클래스들을 말함
- 클래스(Class), 인터페이스(Interface), 배열(Array), 열거(Enum) 타입이 있음
- 실제 객체는 Heap 영역에 저장되며, 참조 타입 변수는 Stack 영역에 실제 객체의 주소를 저장하여 사용 시 객체의 주소를 불러와 사용한다.
- Null 값 존재 가능
✅ 원시 타입과 참조 타입의 차이점
-
Null 포함 여부
- 원시 타입은 Null 포함 불가, 참조 타입은 가능
-
제네릭 타입에서 사용 가능 여부
- 원시 타입은 제네릭 타입에서 사용 불가, 참조 타입은 가능
-
원시 타입이 성능 상 참조 타입보다 좋다
- 원시 타입은 스택 메모리, 참조 타입은 스택에 참조 값이 있고 실제 객체는 힙에 있으므로 사용 시 원시 타입이 상대적으로 빠르고, 참조 타입은 사용 시 Unboxing을 거치므로 느려짐
- 기본적으로 사용하는 메모리 양이 원시 타입이 훨씬 적다.
Stack 영역, Heap 영역
- Stack 영역
- Primitive 타입 변수들이 할당되고 변수의 실제 값들이 저장 됨
- Primitive 타입들은 크기가 정해져 있음
- 메모리에 정적으로 할당되고 컴파일 됨
- 객체를 사용 후 할당되었던 메모리 공간은 반환되어 버려짐
- Heap 영역
- 객체와 배열이 생성되며, 참조 타입들의 주소가 저장 됨
- 크기가 정해져 있지 않음
- 프로그램 실행 시 메모리에 동적으로 할당 됨
- 참조하는 변수가 없으면 Garbage Collector가 제거 함
Boxing, Unboxing
- Boxing: 원시 타입을 참조 타입으로 변환 하는 것
- Unboxing: 참조 타입을 원시 타입으로 변환 하는 것
✅ 원시 타입 및 참조 타입을 파라미터로 전달한다면?
❓원시 타입 및 참조 타입을 파라미터로 전달하면, Call by Value, Call by Reference, Call by Address 중 어떤 것이 맞을까?
✔️ Call by Value : 메소드를 호출할 때, 메소드의 매개 변수(파라미터)가 지정한 변수 값의 복사본을 전달함. 값 자체를 복사해서 전달했기 때문에 수정자의 파라미터 값을 변경해도 호출자의 기존 값은 전혀 영향을 받지 않음
✔️ Call by Reference : 메소드를 호출할 때, 매개 변수로 지정한 값에 대한 참조 주소값 자체를 전달함. 값 자체가 아닌 값을 참조하고 있는 메모리 주소를 전달했기 때문에 수정자에서 값을 수정하면 호출자의 값에 영향을 줌
✔️ Call by Address : 메소드를 호출할 때, 매개 변수로 지정한 값에 대한 참조 주소 값을 복사하여 전달함. Call by Reference와 마찬가지로 주소 값에 대한 정보를 가지고 있기 때문에 수정자에서 수정 시, 호출자의 값에 영향을 줌
✏️ JAVA는 Call by Reference라는 개념이 적용되지 않는다. C나 C++처럼 포인터를 사용해 직접 참조 주소에 접근할 수 있는 반면, JAVA는 참조 주소에 직접 접근할 수 없기 때문.
✏️ 대신, 참조 타입을 사용하면 참조 주소 값을 복사하여 전달하므로, 사용자 입장에서 볼 때는 Call by Reference와 동일한 동작을 수행하는 것으로 보임.
✏️ 결국, JAVA에서는 Call by Value 와 Call by Address를 사용한다고 볼 수 있고, 원시 타입을 매개 변수로 전달할 때는 Call by Value, 원시 타입을 제외한 나머지 참조 타입을 전달할 때는 Call by Address로 동작한다.
참고 Reference