[Java] int vs Integer

굿거리·2023년 4월 5일
0

int vs Integer

자료구조 공부를 하던 초기에 이런 일을 겪은 적이 있었다. 정수형 리스트를 int[]로 변환하고 싶었다.

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0); // 0 추가
int[] arr = list.toArray(new int[1]); // 오류 발생

그랬더니 마지막 줄에서 다음과 같은 오류가 발생했다.


The method toArray(T[]) in the type ArrayList<Integer> is not applicable for the arguments (int[])


ArrayList.toArray() 메서드는 ArrayList<Integer>를 int[]로 바꿀 수 없다는 내용이었다.
당시에는 같은 정수형인데 왜 바꿔주지 않는지 이해가 가지 않았다. 하지만 곰곰이 생각해보니
int와 Integer가 "차이가 없다면 왜 다르게 써왔을까?" 라는 의문이 들었다. int는 변수를 선언할 때, Integer는 자료구조의 객체를 정할 때 쓴다고 생각하고 별 생각 없이 사용해왔던 것 같다.

기본형과 참조형

돌이켜보면 처음 개발 공부를 시작했을 때, int는 주황색이고 소문자로 시작하지만 String은 파란색에 대문자로 시작하는 것에 딱히 의문을 갖지 않았다. 늘 변수를 선언할때 사용했던 것들이지만 근본적으로 다른 것이다.

자바의 값의 타입은 기본형(primitive type)과 참조형(reference type)의 두 가지가 있다.
여기서 int는 정수의 기본형, Integer는 참조형이다.
자바에서 기본형은 딱 8가지가 있다.
정수(byte, short, int, long), 논리(boolean), 문자(char), 실수(float, double)이다.
이를 제외한 나머지 타입은 전부 참조형이다. 참조형은 사용자가 맘대로 생성할 수 있다.

  • 기본형(primitive type)의 특징

    - byte, short, int, long, boolean, char, float, double 총 8가지이며, 각 메모리 크기는 다르다.
    - 선언과 동시에 메모리가 할당된다.
    - 모든 값은 스택(stack)에 저장된다.
    - 저장공간에 실제 값이 저장된다.
    - Null 값을 가질 수 없다.

  • 참조형(reference type)의 특징

    - 위의 기본형 8개를 제외한 모든 타입에 해당된다.
    - 실제 값은 힙(heap)에 저장되며, 스택(stack)에는 그 주솟값을 저장한다.
    - Null 값을 가질 수 있다.

둘은 어떻게 사용할까?

int와 Integer는 같은 정수에 관한 변수이지만 다룰 때 차이점이 존재한다.

[선언]

int intA = 3;
Integer integerA = new Integer(3);

int는 바로 변수명 이후 값을 초기화하면 되지만, Integer는 "원칙적으로" 인스턴스 생성과 동일하게 생성자를 통해 선언해야 한다.

[int <-> Integer 변환]

intA = integerA.intValue(); // 언박싱
integerA = Integer.valueOf(intA); // 박싱

Integer는 int의 Wrapper Class이다.

Wrapper Class는 기본형 변수를 객체처럼 취급하여 사용할 때 필요하다. Wrapper Class는 참조형이며, 이를 통해 매개변수에 객체로서 들어가거나, 메서드를 사용할 수 있다.
이때 int -> Integer를 Boxing, Integer -> int를 UnBoxing이라고 한다.
따라서 int와 Integer는 "원칙적으로" 변환할 때마다 Integer.valueOf()와 Integer.intValue()를 이용해야 한다.

"원칙적으로?" - 자동 박싱과 언박싱

int와 Integer를 오가려면 원칙적으로는 박싱과 언박싱 과정을 계속 거쳐야 한다. 하지만 워낙에 많이 이용하는 데이터 타입이라 그런지, JDK 1.5부터는 오토 박싱과 오토 언박싱을 지원하기 시작했다.

int a = 5;
Integer b = new Integer(5);
System.out.println(a == b); // true
a = b;
b = a;		
Integer c = 5;

위와 같이 int가 Integer를, Integer이 int를 가리킬 수 있으며 a == b도 true를 반환한다.
또한 Integer 선언도 int형처럼 할 수 있다. 이러한 자동 박싱은 메서드에서도 나타난다.

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(Integer.valueOf(3));
list.add(3);
int a = list.get(0).intValue();
int a = list.get(0);

위의 list는 Integer형이므로 원칙적으로는 int형인 3이 들어가면 에러가 발생해야 한다. 따라서 Integer.valueOf(3)으로 박싱을 해서 넣어야 맞지만, int형인 3을 넣어도 컴파일러가 자동으로 Integer.valueOf(3)으로 코드를 변경해준다.

또한 list.get(0)은 Integer형이므로 변수 a에 넣을 수 없다. 그래서 list.get(0).intValue() 처럼 int형으로 변환을 해야 하지만 list.get(0)만 해도 알아서 언박싱을 해준다.

profile
개발자를 향해

0개의 댓글