원시 자료형(primitive data type)은 컴퓨터 과학에서 프로그래밍 언어가 제공하는 자료형 중 하나 - 위키백과
이미지 출처 : https://samdo0812.tistory.com/1
이미지 출처 : https://brunch.co.kr/@leejaelin/38
1개의 바이트는 8개의 비트로 이루어져 있다.
1개의 비트는 [0 | 1] 두 가지의 표현이 가능하다.
이 개념을 사용하면 각 타입이 표현할 수 있는 범위를 파악할 수 있다.
예를 들어 int 같은 경우 4바이트(32비트) 크기를 갖는데, 이 말은 32개의 비트를 사용해서 만들 수 있는 모든 값은 int 자료형에 넣을 수 있다는 의미이다.
char 타입을 제외하고 자바는 +와 -를 다 표현할 수 있다. 앞서 예시를 들었던 int 자료형은 32개의 비트로 표현이 가능하다고 이야기를 했다. 여기에서 가장 첫 번째 비트는 +와 -를 표현하기 위한 비트이다. 해당 비트는 MSB(Most Significant Bit)라고 불려지며, 양수일 경우 0, 음수일 경우 1의 값을 갖는다.
그렇기 때문에 int 자료형의 최대값은 21억 xxx(2의 31승 - 1)가 된다.
예제를 통해서 확인해보겠다. -5를 표현해보면 아래와 같은 과정을 거친다.
1011이 -5가 맞는지 검증해보겠다.
1011(십진수 5) + 0101(방금 계산한 값) == 10000
네 자리 숫자와 네 자리 숫자를 연산했는데 다섯 자리 숫자가 나왔다. 가장 왼쪽에 있던 1을 버리고 0000만을 가져간다. 0000(십진수 0)이 되기 때문에 0101은 -5라고 할 수 있다.
해당 원리를 설명하면 글이 너무 길어진다. 해당 글을 통해 학습을 권장한다.
핵심만 언급하면 컴퓨터는 빼기 연산이 힘들기 때문에, 덧셈만을 사용해서 음수를 처리하기 위해 2의 보수
라는 개념을 사용한다.
메모리는 1바이트를 단위로 하기 때문이다. 어차피 메모리에 올라갈 때 1바이트로 올리기 때문에 1비트로 저장해봤자 얻을 수 있는 이점이 없다.
자바에는 Wrapper 타입(Integer, Long, Character)이라는 게 존재한다. 이들은 Object 자료형을 상속한 객체다. 이들은 객체이기 때문에 null을 표현할 수 있고, 제너릭스에서 활용이 가능하다는 장점을 갖는다. 그럼에도 이펙티브 자바에서는 item 61 - 박싱된 기본 타입보다는 기본 타입을 사용하라
라고 언급한다. 도대체 어떤 장점을 갖는걸까?
Wrapper 타입은 객체이기 때문에 기본적으로 동일성(==) 비교가 통하지 않는다. 해당 부분에서 실수를 했다면 오류를 찾기가 굉장히 어려워진다.
필자는 Integer와 Integer 타입에 대해 == 비교를 했던 적이 있다. Integer 타입의 경우 ==를 통해 동일성을 비교할 수 없다(당연하다). 하지만 -127 ~ 128의 범위에서는 동일성 비교가 된다. 해당 범위 내의 값들은 static 선언이 되어 있어 동일한 객체를 가져다가 사용하기 때문이다.
문제에 있던 예시와 디버깅을 위해 만들었던 수많은 예시들은 해당 범위 내의 숫자들이라 정상적으로 동작했다.
만약 코딩테스트가 아니라 실제 로직이었다면 문제가 발생하기 전까지 예상하지도 못했고, 문제가 발생해도 원인을 찾는게 어려웠을 것이다.
원시 타입은 항상 유효한 값을 가지고 있음을 보장한다. 값을 사용할 때 NullPointException을 고려할 필요가 없어 안전하게 값을 다룰 수 있다.
상황에 따라 다르겠지만 null이 필요 없는 상황이라면 원시 자료형을 사용하는 게 프로그램의 안정성을 높여줄 수 있다.
이 부분 관련해서는 책의 예시가 와닿지 않아서 제가 생각하는 장점을 적었습니다.
Wrapper 타입은 연산하는 과정에서 기본 타입으로 변환이 일어난다. 만약 반복문 등을 사용하게 된다면 Wrapper 타입을 언박싱하면서 성능에 문제가 발생할 수 있다.
상황에 따라 원시 타입과 Wrapper타입을 적절하게 사용하자. 그리고 Wrapper 타입이 객체라는 걸 꼭 인지하고, 연산이 필요한 경우에는 신경써서 확인하자.