▶오늘의 주제 : 참조 타입과 참조 변수
▶자바의 타입은 기본 타입과 참조 타입으로 분류됩니다.
▶기본 타입과 참조 타입
: 기본 타입으로 선언된 변수와 참조 타입으로 선언된 변수의 차이점은 저장되는 값입니다.
- 기본 타입 : byte, char, short, int, long. float, double, boolean 변수는 실제 값을 변수 안에 저장합니다.
- 참조 타입 : 배열, 열거, 클래스, 인터페이스 변수는 메모리 번지를 변수 안에 저장합니다. 변수를 통해 객체를 참조한다는 뜻입니다.
▶메모리 사용 영역
: JVM은 운영체제에서 할당받은 메모리 영역을 다음과 같이 세부 영역으로 구분해서 사용합니다.
- 메소드 영역 : 메소드 영역에는 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스별로 정적 필드와 상수, 메소드 코드, 생성자 코드 등을 분류해서 저장
- 힙 영역: 객체와 배열이 생성되는 영역 / 참조하는 변수나 필드가 없으면 의미 없는 객체가 되긱 때문에 JVM이 이것을 쓰레기로 취급하고 쓰레기 수집기를 실행시켜 자동으로 제거
- JVM 스택 영역 : 메소드를 호출할 때마다 프레임을 추가하고 메소드가 종료되면 프레임을 제거
▶참조 변수의 ==, !=연산
동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용됩니다.
refVar1 == refVar2. // 결과: false
refVar2 != refVar2. // 결과 : true
refVar2 == refVar3. // 결과 true
refVar2 != refVar3. // 결과 false
▶null과 NullPointerException
참조 타입 변수는 힙 영역의 객체를 참조하지 않는다는 듯으로 null(널) 값을 가질 수 있습니다. null값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에서 생성됩니다.
자바는 프로그램 실행 도중에 발생하는 오류를 예외라고 부릅니다. 참조 변수를 사용하면서 가장 많이 발생하는 예외 중 하나로 NullPointerException이 있습니다.
refVar1 == null // 결과 false
refVar2 != null // 결과 true
refVar2 == null. // 결과 true
refVar2 != null //결과 false
int[ ] intArray = null;
intArray [0] = 10; //NullPointException, 배열이 없는데 어떻게 0번째 위치에 저장?
String str = null;
System.out.println ("총 문자수: " + str.length()); // str이 참조하는 객체가 없기 때문에 NullPointException이 발생
▶String 타입
자바는 문자열을 String 변수에 저장하기 때문에 다음과 같이 String 변수를 우선 선언해야 합니다.
문자열을 저장하려면 큰따음표로 감싼 문자열 리터럴을 대입합니다.
String 변수;
변수 = "문자열";
String 변수 = "문자열";
String name;
name = "신용권";
String hobby = "자바";
자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 되어 있습니다. 다음과 같이 name1과 name2 변수가 동일한 문자열 리터럴인 "신용권"을 참조할 경우 name1과 name2는 동일한 String 객체를 참조하게 됩니다.
String name1 = "신용권";
String name2 = "신용권";
▶ new 연산자
: new 연산자를 사용해서 직접 String 객체를 생성시킬 수도 있습니다. new 연산자는 힙 영역에 새로운 객체를 만들 때 사용하는 연산자로 객체 생성 연산자라고 합니다.
String name1 = new String("신용권");
String name2 = new String("신용권");
name1과 name2는 동일한 문자열 리터럴로 생성된 객체로 참조하기 때문에 name1 == name2 의 결과는 true가 나옵니다. 그러나 name3은 new 연산자로 string 객체를 별도로 생성했기 대문에 name1 == name3은 false가 나옵니다.
String name1 = "신용권";
String name2 = "신용권";
String name 3 = new String("신용권");
name1 == name2; // true
name1 == name3; // false
동일한 String 객체이건 다른 String 객체이건 상관없이 내부 문자열을 비교하고 싶을 때에는 String 객체의 equals()메소드를 사용해야 합니다. equals() 메소드는 원본 문자열과 매개값으로 주어진 비교문자열이 동일한지 비교한 후 true 또는 false를 리턴합니다.
boolean result = str1.equals(str2):
str1 : 원본 문자열
str2 : 비교 문자열
public class Practice {
public static void main(String[] args) {
String strVar1 = "신민철";
String strVar2 = "신민철";
if(strVar1 == strVar2) {
System.out.println("strVar1과 strVar2는 참조가 같음");
} else {
System.out.println("strVar1과 strVar2는 참조가 다름");
}
if(strVar1.equals(strVar2)) {
System.out.println("strVar1rhk strVar2는 문자열이 같음");
}
String strVar3 = new String("신민철");
String strVar4 = new String("신민철");
if(strVar3 == strVar4) {
System.out.println("strVar3과 strVar4는 참조가 같음");
} else{
System.out.println("strVar3과 strVar4는 참조가 다름");
}
if(strVar3.equals(strVar4)) {
System.out.println("strVar3과 strVar4는 문자열이 같음");
}
}
}
▶쓰레기 수집기
String 변수는 참조 타입이므로 초기값으로 null을 대입할 수 있습니다. 이때 null은 String 변수가 참조하는 String 객체가 없다는 뜻입니다.
String hobby = null;
String hobby = "여행";
hobby = null;
hobby 변수가 String 객체를 참조하였으나, null을 대입함으로써 더 이상 String 객체를 참조하지 않도록 할 수도 있습니다. 참조를 잃은 String 객체는 어떻게 될까요? JVM은 참조되지 않은 객체를 쓰레기 객체로 취급하고 쓰레기 수집기를 구동시켜 메모리에서 자동 제거합니다.
▶마무리
- 기본 타입: byte, short, char, int, long, float, double, boolean 타입을 말하며 이들 타입의 변수에는 값 자체가 저장됩니다.
- 참조 타입: 기본 타입을 제외한 배열, 열거, 클래스, 인터페이스 등을 말합니다. 참조 타입의 변수에는 객체의 번지가 저장됩니다.
- 메모리 사용 영역: JVM은 운영체제에서 할당받은 메모리 영역을 메소드 영역, 힙 영역, 스택 영역으로 구분해서 사용합니다. 메소드 영역에는 정적 필드, 상수, 메소드 코드, 생성자 코드가 위치하며, 힙 영역에는 객체가 생성됩니다. 그리고 스택 영역에는 변수가 생성됩니다.
- 번지 비교 : 비교 연산자 (==, !=)가 기본 타입에서 사용되면 값을 비교하지만, 참조 타입에서 사용되면 번지를 비교합니다. ==이 true가 나오면 같은 객체를 참조한다는 뜻이고 false가 나오면 다른 객체를 참조하는 뜻입니다.
- null : 참조 타입 변수는 객체를 참조하지 않는다는 뜻으로 null 값을 가질 수 있습니다. null 값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에서 생성됩니다.
- NullPointerException : 참조 변수가 null을 가지고 있을 경우에는, 참조 객체가 없으므로 참조 변수를 통해 객체를 사용할 수 없습니다.
'Java' 카테고리의 다른 글
Java - 열거 타입 (0) | 2022.11.12 |
---|---|
Java - 배열 (0) | 2022.11.11 |
Java - 반복문: for문, while문, do-while (0) | 2022.11.10 |
Java - 조건문: if문, switch문 (0) | 2022.11.10 |
Java - 연산자의 종류 (0) | 2022.11.08 |