자바의 타입은 값을 직접 갖는 쪽과 값이 있는 곳을 갖는 쪽으로 나뉜다. 복사와 비교, 메서드 전달의 동작이 전부 이 차이에서 갈린다.

변수와 리터럴

int i = 1;

int는 정수 타입을 나타내는 키워드다. 키워드란 public, class, static, while처럼 자바가 미리 정해둔 예약어를 말한다. i는 변수, 하나의 값을 담을 수 있는 메모리 공간의 이름이다. 1은 리터럴, 변수에 입력되는 값 자체다.

변수를 선언한다는 것은 이 이름으로 어느 위치의 메모리를 얼마만큼 쓰겠다고 정하는 일이다. 정수 하나를 저장하려면 4바이트가 필요하고, 그 4바이트에 1이 00000000 00000000 00000000 00000001로 저장된다.

리터럴은 프로그램이 시작할 때 함께 로딩되어 상수 풀이라는 메모리 공간에 놓인다. int num = 3;이라고 쓰면 값 3이 먼저 메모리 어딘가에 적혀 있어야 하고, 그 값이 다시 num의 메모리로 복사된다.

리터럴의 기본 크기

자바는 정수를 4바이트 int로, 실수를 8바이트 double로 인식한다. 다른 타입으로 두고 싶으면 리터럴에 표시를 해야 한다.

long y = 5L;      // L을 붙여야 long 리터럴
float y = 5.2F;   // F를 붙여야 float 리터럴

long num = 12345678900;은 리터럴이 int 범위를 벗어나서 오류가 난다. 상수 풀에서도 정수의 기본 크기는 4바이트다. 8바이트로 처리하라고 L을 붙여 컴파일러에게 알려줘야 한다.

초기화 규칙

초기화 규칙은 변수가 어디에 있느냐로 갈린다. 메서드 안의 지역 변수는 반드시 초기화해야 하고, 그러지 않으면 variable 변수명 might not have been initialized 오류가 난다. 클래스 안에 선언된 필드는 초기화하지 않아도 기본값이 자동으로 들어간다.

변수명 규칙

변수명이라고 아무 이름이나 되지는 않는다. 첫 글자는 문자나 $, _ 만 가능하고 두 번째부터는 숫자도 섞을 수 있다. $_ 외의 특수문자는 쓸 수 없고 길이 제한은 없다. 키워드와 true, false, null도 변수명이 되지 못한다.

기본형

정해진 크기의 메모리를 확보해 값을 직접 갖는다. byte, short, int, long, char, float, double, boolean 여덟 개가 전부이고 모두 소문자 키워드다.

정수형문자형실수형논리형
1바이트byteboolean
2바이트shortchar
4바이트intfloat
8바이트longdouble

boolean은 참과 거짓만 담으니 1비트면 충분한데도 1바이트를 쓴다. 컴퓨터가 자료를 다루는 최소 단위가 1바이트이기 때문이다.

참조형

기본형 여덟 개가 아닌 나머지 전부다. 클래스와 인터페이스, 배열이 여기 속한다. 값을 직접 갖지 않고 값을 참조하므로, 변수에는 실제 데이터 대신 데이터가 놓인 곳의 주소가 들어 있다.

주소를 담는다는 성질이 여러 곳에서 드러난다. 메서드에 넘기면 주소가 복사되므로 호출한 쪽과 같은 객체를 건드린다. 얕은 복사와 깊은 복사 == 비교는 내용이 아니라 주소를 견주는 일이다. equals와 hashCode 배열 역시 참조형이라 같은 규칙을 따른다. 배열

클래스 이름을 대문자로 시작하는 것은 오래된 관례이지, 참조형을 가르는 기준은 아니다.

참고

원본은 참조형을 “첫 번째 글자가 대문자이면서 기본형이 아닌 모든 타입”이라고 적었다. 첫 글자 대문자는 클래스 이름을 짓는 관례일 뿐 언어가 정한 규칙이 아니다. 자바 언어 명세는 참조형을 클래스 타입, 인터페이스 타입, 타입 변수, 배열 타입으로 정의하고 이름의 대소문자는 조건에 넣지 않는다. int[]는 소문자로 시작하지만 배열 타입이므로 참조형이고, 소문자로 시작하는 클래스를 선언해도 컴파일은 그대로 통과한다. JLS 4.3

관련

출처