Java 파트4-1. 참조타입과 참조변수

1. 시작하기 전에


그림1

  • 기본 타입 : 정수, 실수, 문자, 논리 리터럴 저장
  • 참조 타입 : 객체의 번지를 참조하는 타입
    • 배열, 열거, 클래스, 인터페이스


2. 기본 타입 변수와 참조 타입 변수의 차이점


그림2

기본 타입 변수에는 직접 값이 저장되지만, 참조 타입 변수에는 직접 값이 저장되는게 아니고 힙 영역에 생성된 객체의 번지가 저장된다.


3. 메모리 사용 영역


그림3

.java 소스 코드를 컴파일 하면 .class라는 바이트 코드 파일이 생성된다. 코드에서 바이트 코드 파일을 사용하면 바이트 코드 파일이 메소드 영역에 로딩된다.(클래스 바이트 코드를 메소드 영역에 저장하는 것) 이렇게 저장된 클래스를 가지고 객체를 만든다던지, 변수를 생성한다든지 사용한다. 즉, 메소드 영역에는 클래스의 바이트 코드들이 저장된다고 생각하면 된다. 힙 영역은 클래스로부터 생성된 객체들이 저장되는 곳이다.

  • 메소드 영역 : 클래스 별로 정적 필드, 상수, 생성자, 메소드 코드 등을 분류해 저장
  • 힙 영역 : 객체와 배열이 생성되는 영역
  • JVM 스택 영역 : 메소드가 호출되면 프레임이 추가되고, 메소드가 종료되면 프레임이 제거된다.

JVM 스택 영역
메소드를 호출할 때마다 프레임이 추가되고, 메소드가 종료되면 해당 프레임이 제거된다.

그림4

if문이 선언된 블록이 끝나면 v2,v3는 프레임 영역에서 제거된다.

그림5

기본 타입 변수와 달리 참조 타입 변수는 스택 영역에 값이 저장되는게 아니라 힙 영역에 생성된 객체의 주소가 저장된다.

4. 참조 변수의 == != 연산


동일 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용한다.

그림6

refVar1 == refVar2 // false
refVar1 != refVar2 // true

refVar2 == refVar3 // true
refVar2 != refVar3 // false


그림7

참조 타입 변수는 객체를 참조하지 않는다는 뜻으로 null값을 가질 수 있다.

refVar1 == null // false
refVar1 != null // true

refVar2 == null // true
refVar2 != null // false


5. Error, Exception


  • Error : 하드웨어, OS 문제때문에 발생
  • Exception(예외) : 실행하는 도중 발생
    • NullPointException : 참도 타입 변수가 null 상태에서 존재하지 않는 객체의 데이터나 메소드를 사용할 경우 발생 -> 해당 참조 변수가 객체를 참조하도록 수정하여 해결
int[] intArray = null;
intArray[0] = 10; // NullPointException , 배열이 없는데 어떻게 0번째 위치에 저장?

String str = null;
System.out.println("총문자수: " + str.length()); // NullPointException

6. String 타입


그림8

  • String 변수에 문자열 리터럴을 대입할 경우 String 객체로 생성되고 변수가 String 객체를 참조한다.
  • 문자열 리터럴이 동일한 경우 같은 String 객체의 번지를 공유한다.

new 연산자

  • 객체 생성 연산자
  • 힙 영역에 새로운 String 객체를 생성
String name1 = new String("신용권");
String name2 = new String("신용권");

그림9

앞서 문자열 리터럴이 동일한 경우 하나의 객체의 주소를 공유한다고 했다. 하지만 new를 사용하여 새로운 객체를 만들 경우 문자열이 같아도 다른 객체를 만들 수 있다. 이를 간단히 비교해보자.

String name1 = "신용권";
String name2 = "신용권";
String name3 = new String("신용권");

name1 == name2; // true
name1 == name3; // false

문자열 비교

자바에서는 문자열 비교시

  • == : 번지를 비교 -> 문자열을 비교하는게 아니라 잘 사용하지 않음
  • equals(): 문자열 비교

equals는 안에 있는 내용물을 비교(다른 주소를 가지더라도), ==는 같은 주소를 참조하는지를 비교하는 것으로 알아두면 된다.

쓰레기 수집기

String 변수 초기값으로 null 대입시 String 변수가 참조하는 객체가 없음을 의미한다.

String hobby = "여행";
hobby = null;

그림10

원래 변수 hobby는 힙 영역에 String 객체를 참조하고 있었다. 그런데 null로 바뀌면서 참조하는 번지수가 사라지게 된다. 그렇다면 힙 영역에 있던 객체는 참조를 잃어버린게 된다. 자바는 힙 영역에 참조 없이 단독으로 생성되게 된 객체를 쓰레기 객체라고 한다. 참조가 있어야만 이 객체를 찾아서 이용할 수 있는데 없다면 사용할 수가 없기 때문이다. 그래서 쓰레기 객체를 쓰레기 수집기(Garbage collector)가 이런 힙 영역에 참조를 잃은 객체들을 제거한다. 따라서 사용자가 따로 처리할 필요가 없다.

정리하기

  • 기본 타입 : byte, short, char, int, long, float, double, boolean 타입은 변수에 값 자체가 저장
  • 참조 타입 : 기본 타입을 제외한 배열, 열거, 클래스, 인터페이스는 변수에 객체의 번지가 저장
  • 메모리 사용 영역 : JVM은 운영체제에서 할당받은 메모리 영역을 메소드 영역, 힙 영역, 스택 영역으로 구분해서 사용
  • 번지 비교 : 비교 연산자가 기본 타입에서 사용되면 값을 비교하지만 참조 타입에서 사용되면 번지를 비교
    • String 객체 문자열 비교시 equals() 사용
  • null : 참조 변수는 객체를 참조하지 않는다는 의미로 null 값을 가질 수 있다.
  • NullPointException : 참조 변수가 null 일 때 참조 변수를 통해 존재하지도 않는 객체를 사용하려고 할 경우 발생

본 포스팅은 ‘혼자 공부하는 자바’를 읽고 공부한 내용을 바탕으로 작성하였습니다.


© 2021. By Backtony