잡설 

 문득 코딩테스트 공부를 하며 코드를 작성하다가 현타가 왔다. 원래 중간중간 나에게 질문을 하는 버릇이 있는데, 평소에 익숙하게 사용하던 코드를 보다가 단순한 의문이 들었다. HashSet을 사용하다가 타입 파라미터.. ->  제네릭 ..-> Reference Type , Primitive Type 이렇게 의식의 흐름대로 생각을 따라가며 정리를 하다보니 미흡한 부분이 있었고 이 참에 블로그 첫 게시글을 시작으로 부족했던 개념들을 복습할겸 정리해보기로 했다. 

 

Primitive Type(원시 타입) vs Reference Type(참조 타입)

 먼저, 래퍼클래스를 이해하기 위해서는 primitive type 변수와, reference type 변수의 차이를 이해해야 한다. 자바에서는 아래 총 8가지의 primitive type을 정의하고 제공한다.

  타입 할당되는 메모리크기 기본값 데이터의 표현범위
논리형 boolean 1 byte false true,false
정수형 byte 1 byte 0 -128~127
short 2 byte 0  -32,768 ~ 32,767
int (기본형) 4 byte 0 -2,147,483,648 ~ 2,147,483,647
long 8 byte 0L -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
실수형 float 4 byte 0.0F (3.4 X 10-38) ~ (3.4 X 1038) 의 근사값
double (기본형) 8 byte 0.0  (1.7 X 10-308) ~ (1.7 X 10308) 의 근사값
문자형 char 2 byte (유니코드) '\u000' 0 ~ 65,535

primitive type의 특징으로는 다음과 같다.

  • 모두 소문자로 시작된다.
  • 비객체 타입이므로 null 값을 가질 수 없다. 
  • 제너릭에서 타입파라미터로 사용될 수 없다.
  • stack에 바로 사용할 수 있는 값(실제 값)을 바이트 단위로 저장한다.

 reference type의 특징으로는 다음과 같다.

  • 기본형 과는 달리 실제 값이 저장되지 않고, 자료가 저장된 공간의 주소를 저장한다.
  • 즉, 실제 값은 다른 곳에 있으며 값이 있는 주소를 가지고 있어서 나중에 그 주소를 참조해서 값을 가져온다.
  • 메모리의 힙(heap)에 실제 값을 저장하고, 그 참조값(주소값)을 갖는 변수는 스택에 저장
  • 참조형 변수는 null로 초기화 시킬 수 있다
더보기

쉽게 얘기하면 reference type 은 위 8가지의 primitive type 자료형을 제외한  모든 자료형을 reference type 이라고 볼 수 있다. 

ex) 기본적으로 제공하는 클래스, 프로그래머가 스스로 만든 클래스, 배열, 열거 타입 등...

 

Wrapper Class(래퍼 클래스)

코딩을 하다보면 primitive type의 변수를 reference type 변수로 변경해야할 때가 생기곤 한다. 예를들어 메서드 파라미터의 타입이 reference type 이라면 primitive type의 변수를 그대로 사용할 수 없다. 이럴 때는 기본타입의 변수를 객체타입의 변수로 변환해 주는 작업이 필요하다. 이렇게 8개의 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 래퍼 클래스(Wrapper class)라고 한다.  

primitive type(기본타입) wrapper class(래퍼클래스)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

 

Boxing & Unboxing

 래퍼 클래스(Wrapper class)는 산술 연산을 위해 정의된 클래스가 아니므로, 인스턴스에 저장된 값을 변경할 수 없다. 단지, 값을 참조하기 위해 새로운 인스턴스를 생성하고, 생성된 인스턴스의 값만을 참조할 수 있다.  그렇기 때문에 값을 변경할 때에는 래퍼 클래스를 언박싱 한 뒤에 값을 변경하고 다시 박싱을 해야하는 중간단계를 거쳐야 한다.

 

  • Boxing : 기본 타입의 데이터 → 래퍼 클래스의 인스턴스로 변환
  • UnBoxing : 래퍼 클래스의 인스턴스에 저장된 값 → 기본 타입의 데이터로 변환
Integer num1 = new Integer(1); // boxing
Integer num1 = 1; // 이런식으로도 표현 가능

Double num2 = new Double(1.11); // boxing
Double num2 = 1.11; // 이런식으로도 표현 가능



int n1 = num1.intValue(); // unboxing

n1 = n1 + 100; // 101 (값변경)
num1 = new Integer(n1); //boxing (재포장)


double n2 = num2.doubleValue(); // unboxing

n2 = n2 + 100.0; // 101.11 (값변경)
num2 = new Double(n2); //boxing (재포장)

 각 Wrapper Class 의 언박싱 메서드들은 다음과 같다.

메서드 반환값 설명
byteValue() byte 객체의 값을 byte 값으로 변환하여 반환
shortValue() short 객체의 값을 short 값으로 변환하여 반환
intValue() int 객체의 값을 int 값으로 변환하여 반환
longValue() long 객체의 값을 long 값으로 변환하여 반환
floatValue() float 객체의 값을 float 값으로 변환하여 반환
doubleValue() double 객체의 값을 double 값으로 변환하여 반환
charValue() char 객체의 값을 char 값으로 변환하여 반환
booleanValue() boolean 객체의 값을 boolean 값으로 변환하여 반환 

 기능적 편의성을 위하여 오토 박싱 / 언박싱을 제공하지만, 다른 타입간의 형 변환은 어플리케이션의 성능에 영향을 미치게 된다. 비록 사소한 차이 일지라도 어플리케이션의 성능 측면에서 봤을때 반드시 필요한 상황인지 한번 생각해 볼 필요가 있을 것 같다.

오토 박싱(AutoBoxing)과 오토 언박싱(AutoUnBoxing)

 JDK 1.5부터는 박싱과 언박싱이 필요한 상황에서 자바 컴파일러가 이를 자동으로 처리해 준다고 한다. 이렇게 자동화된 박싱과 언박싱을 오토 박싱(AutoBoxing)과 오토 언박싱(AutoUnBoxing)이라고 부른다.

/* 기존 박싱 & 언박싱 */
Integer num = new Integer(17); // 박싱
int n = num.intValue();        // 언박싱

/* 오토 박싱 & 언박싱 */
Integer num = 17; // new Integer() 생략
int n = num; // intValue() 생략

참조

'Java > Base' 카테고리의 다른 글

[Java] Immutable Object(불변객체)  (0) 2024.04.21

+ Recent posts