자바의 데이터 타입에는 크게 두 가지 기본 타입과 참조타입이 있다.
기본 타입 (Primitive type)
정수, 실수, 문자, 논리 리터럴을 저장하는 타입을 말하고 원시 타입이라고도 부른다.
- 정수형 : byte, short, int, long
- 실수형 : float, double
- 문자형 : char
- 논리형 : boolean
실제 데이터 값을 저장하는 타입
참조 타입 (Reference type)
간단하게 말하자면 기본 타입을 제외한 타입들을 말한다. 객체의 주소를 저장하는 타입이다.
ex) 문자열, 배열, 열거, 클래스, 인터페이스
Java에서 실제 객체는 Heap 영역에 저장되며 참조 타입 변수는 스택 영역에 실제 객체들의 주소를 저장하여 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다.
Stack 영역
스택 영역에는 기본타입 변수가 할당되고 변수의 실제 값들이 저장된다.
참조 타입의 변수들은 이 스택 영역에서 힙 영역에 생성된 객체들의 주소 값을 저장하고 있는다.
객체 안의 메소드의 작업이 종료되면 할당되었던 메모리 공간은 반환되어 비워진다.
Heap 영역
힙 영역에는 객체와 배열이 생성된다.
그리고 참조타입(배열, 클래스, 인터페이스 등)들이 이 객체들의 주소를 스택 영역에 저장한다.
기본타입 변수들과는 다르게 크기가 정해져 있지 않다.
프로그램 실행시 메모리에 동적으로 할당된다.
참조하는 변수가 없으면 자바의 가비지 컬렉터가 제거한다.
가비지 컬렉터(Garbage collector) : 메모리의 힙 영역에 할당된 더 이상 사용되지 않는 객체를 제거 하는 역할
이렇게 객체를 제거하며 메모리가 관리된다.
기본 타입과 참조 타입의 차이
1. Null 포함 가능 여부
기본 타입은 null을 담을 수 없지만 참조 타입은 가능하다.
int i = null;//불가능
Integer integer = null; //가능
2. 제네릭 타입에서 사용 가능 여부
마찬가지로 기본 타입은 제네릭 타입에서 사용할 수 없지만, 참조 타입은 가능하다.
List<int> i;//불가능
List<Integer> integer;//가능
3. 접근 속도, 메모리 양
원시 타입은 '스택' 메모리에 값이 존재합니다. 반면에 참조 타입은 하나의 인스턴스이기 때문에 '스택'메모리에는 참조값만 있고,
실제 값은 힙 메모리에 존재하게 됩니다. 그리고 값을 필요로 할 때마다 언박싱 과정을 거쳐야 하니
원시 타입과 비교해서 접근 속도가 느려지게 됩니다.
(예외적으로 엄청 큰 숫자를 복사해야 한다면, 참조값만 넘길 수 있는 참조 타입이 좋을 수 도 있습니다.)
참조변수의 ==, != 연산
비교 연산자(==, !=)가 기본 타입에서 사용되면 변수의 값이 같은지, 다른지 비교하지만, 참조타입에서 사용되면 동일한 객체를 참조하는지 아닌지 번지를 비교한다. ==가 true가 나오면 같은 객체를 참조하고 false가 나오면 다른 객체를 참조한다는 뜻이다.
null, NullPointerException
null
- 참조 타입 변수는 객체를 참조하지 않는다는 뜻으로 null 값을 가질 수 있다.
- null값은 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조변수는 스택 영역에 생성된다.
NullPointException
- 참조변수를 사용하면서 가장 많이 발생하는 예외 중 하나
- 참조변수가 null을 가지고 있을 경우 참조 객체가 없으므로 참조 변수를 통해 객체를 사용할 수 없다.
- 만약 null 상태에서 있지도 않은 객체의 필드(데이터)나 메소드를 사용하는 코드를 실행하면 NullPointerException이 발생한다.
int[] intArray=null;
intArray[0]=10;
//intArray는 배열변수로, 참조변수라 null로 초기화 가능
//intArray 변수가 참조하는 배열 객체가 없기 때문에 10을 저장하려하면 NullPointerException 발생
String 타입
- String 변수를 선언하고 동시에 문자열을 저장할 수 있다.
String 변수 ="문자열";
- 2개의 String 변수를 선언하고 문자열을 저장할 수 있다.
String name; name="신용권"; String hobby="자바";
문자열 리터럴이 동일하다면 String 객체를 공유할 수 있다.
String name1="신용권"; String name2="신용권";
//=> name1과 name2 변수가 동일한 문자열 리터럴인 "신용권"을 참조할 경우 name1과 name2는 동일한 String 객체를 참조하게 된다.
- 일반적으로 변수에 문자열 저장할 경우 문자열 리터럴 사용
- new 연산자를 사용해 직접 String 객체를 생성시키는 것도 가능하다.
// new 연산자 : 객체 생성 연산자, 힙 영역에 새로운 객체를 만들 때 사용하는 연산자다.
String name3= new String("신용권") String name4= new String("신용권")
//name3과 name4는 서로 다른 String 객체를 참조, 객체의 번지가 달라진다
- 참조를 잃은 String 객체는?
JVM이 참조되지 않은 객체를 쓰레기 객체로 취급하고 쓰레기 수집기(Garbage Collector)구동, 메모리에서 자동 삭제한다.
문자열 리터럴 / new 연산자 생성에 따른 비교 연산자(==)의 결과 차이
String name1="신용권";
String name2="신용권";
String name3= new String("신용권")
//String name1==String name2
//=> 결과 :true
//=> name1, name2 동일한 문자열 리터럴로 생성된 객체를 참조하기 때문
//String name1==String name3
//=> 결과 :false
//=> name3은 new 연산자로 String 객체를 별도로 생성했기 때문에 name1과 번지가 같지 않다.
참고블로그
'Java > Java' 카테고리의 다른 글
[Java]배열(Array) 선언 및 초기화,복사 (0) | 2022.11.11 |
---|---|
[Java]메모리 구조 (0) | 2022.11.11 |
[Java]별 찍기 피라미드 (0) | 2022.11.10 |
[Java]BufferedReader (0) | 2022.11.10 |
[Java]Integer.parseInt란 ? (0) | 2022.11.10 |
댓글