목표
자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.
학습할 것
- 프리미티브 타입 종류와 값의 범위 그리고 기본 값
- 프리미티브 타입과 레퍼런스 타입
- 리터럴
- 변수 선언 및 초기화하는 방법
- 변수의 스코프와 라이프타임
- 타입 변환, 캐스팅 그리고 타입 프로모션
- 1차 및 2차 배열 선언하기
- 타입 추론, var
프리미티브 타입 종류와 값의 범위 그리고 기본 값
자바는 C언어와 달리 포인터가 없기 때문에 실제 연산에 사용되는 것은 모두 프리미티브 타입이다.
(사진 출처 - 블로그)
프리미티브 타입에는 모두 8개의 자료형이 있으며 크게 논리형, 문자형, 정수형, 실수형으로 구분된다.
- 논리형
- boolean : 1 bit로도 충분히 표현할 수 있지만 메모리 주소 크기가 1byte이므로 모든 자료형의 최소 크기는 1 byte이다.
- char : C에서는 ASCII 코드를 사용해 char가 1 byte이지만, 자바에서는 유니코드를 지원하여 2byte 크기를 갖는다.
- 정수형
- byte : 정수형 자료형 중 가장 작은 범위의 값을 저장한다. (1 byte = 8 bit 이므로 2^8(256)개의 수를 저장)
- short / int / long : 정수형 자료형의 경우 값의 범위는 -2^n-1 ~ 2^n-1 - 1 이다.
- 실수형 (주로 double 사용)
- float / double : 주로 double이 사용된다.
프리미티브 타입과 레퍼런스 타입
자료형은 크게 기본형 (primitive)과 참조형 (reference)로 나뉜다. 프리미티브 타입은 실제 값이나 데이터를 저장하는 반면 레퍼런스 타입은 값이 저장되어 있는 주소를 저장한다.
- Primitive Type
- 계산을 위한 실제 값을 저장한다.
- Reference Type
- 위 8개의 프리미티브 타입을 제외한 나머지 타입으로 객체의 주소를 저장한다.
레퍼런스 타입을 선언할 때는 변수의 타입으로 클래스 이름을 사용한다. 따라서 클래스의 이름이 레퍼런스의 타입이 된다. 아래는 Date 클래스 타입의 레퍼런스 변수 today를 선언한 것이다. 레퍼런스 변수는 값으로 null 또는 객체의 주소를 갖는다. 연산자 new 의 결과는 생성된 객체의 주소이다. 즉, 새롭게 생성한 객체의 주소를 today라는 변수에 저장하고, 이 레퍼런스 변수를 통해 생성된 객체를 사용할 수 있다.
Date today = new Date();
리터럴
리터럴 설명에 앞서 상수에 대한 설명을 하고 차이점에 대해 알아보자.
상수도 변수처럼 값을 저장할 수 있는 공간이기는 하다. 다른 점은 한 번 값을 저장하면 다른 값으로 변경할 수 없다는 점이다. 변수와 똑같이 선언하되 앞에 final 키워드만 붙이고, 선언과 동시에 초기화를 해주어야 한다.
final MAX_VALUE; // (X)
final MAX_VALUE = 100; // (O)
프로그래밍에서 상수를 변경할 수 없는 값으로 지정했기 때문에 우리가 흔히 "상수"라고 쓰는 100, 1234, 'A' 등의 값을 리터럴이라고 부르는 것 뿐이다. 변수, 상수, 리터럴을 요약하면 다음과 같다.
- 변수 (variable) : 하나의 값을 저장하기 위한 공간
- 상수 (constant) : 값을 한 번만 저장할 수 있는 공간 (read only)
- 리터럴 (literal) : 그 자체로 값을 의미하는 것 (read-write)
변수 선언 및 초기화하는 방법
int age; // 변수 age 선언
int age = 26; // 변수 age를 선언하고 26으로 초기화
변수를 선언하면 메모리 빈 공간에 변수타입에 알맞은 크기의 저장 공간이 확보된다. 위의 예에서는 int 형으로 선언했기 때문에 4 byte 만큼의 저장 공간이 확보된다. 그리고 이 저장 공간을 변수이름으로 사용할 수 있는 것이다.
변수는 선언 후에 자유롭게 사용할 수 있으나 그 전에 초기화해주는 것이 좋다. 메모리는 공유 자원이기 때문에 초기화해주지 않으면 쓰레기값이 들어가기 때문이다. 따라서 변수를 초기화한다는 것은 변수를 사용하기 전에 처음으로 값을 저장한다고 이해하면 된다.
변수의 스코프와 라이프타임
변수의 스코프는 해당 변수를 사용할 수 있는 범위이다. 대개 변수가 선언된 클래스의 중괄호 내에서 사용 가능하다. 변수는 클래스 변수, 인스턴스 변수, 지역변수 세 종류가 있다. 각 변수가 무슨 종류인지 알기 위해서는 변수가 선언된 위치를 확인하면 된다.
class Card {
String kind; // 인스턴스 변수
int number;
static int width = 100; // 클래스 변수
static int height = 250;
void shuffle() {
int count = 0; // 지역변수
}
}
각 Card 인스턴스는 자신만의 무늬와 숫자를 유지하고 있어야 하기 때문에 인스턴스 변수로, 폭과 높이는 모든 인스턴스가 공통적으로 같은 값을 유지해야 하기 때문에 클래스 변수로 선언했다. count는 메서드 내에 있기 때문에 지역변수이다.
- 지역변수 : 멤버변수를 제외한 나머지 변수들
- 메서드 내에 선언되어 메서드 내에서만 사용 가능하다. (메소드 종료 시 소멸)
- 클래스 영역 이외의 영역에 선언하며 변수 선언문이 수행되었을 때 생성된다.
- 스코프 : 선언된 코드 블록 (메서드) 내
- 라이프타임 : 해당 코드 블록을 벗어날때까지
- 클래스 변수 : 멤버변수 중 static 키워드가 붙은 변수
- 모든 인스턴스가 공통된 저장공간을 공유한다.
- 클래스 영역에 선언하며 클래스가 메모리에 올라갈 때 생성된다.
- 스코프 : 클래스 전체
- 라이프타임 : 클래스가 메모리에 로드되는 동안, 또는 프로그램이 종료될때까지
- 인스턴스 변수 : 멤버변수 중 static 키워드가 붙지 않은 변수
- 각 인스턴스가 독립적인 저장공간을 갖는다.
- 클래스 영역에 올라가며 인스턴스가 생성되었을 때 생성된다.
- 스코프 : 정적 메서드를 제외한 클래스 전체
- 라이프타임 : 객체가 메모리에 존재할때까지
타입 변환, 캐스팅 그리고 타입 프로모션
코드를 작성하다 보면 서로 다른 자료형 간의 연산을 해야 하는 경우가 있다. 이럴 때 변수나 리터럴의 타입을 변환하는 것이 형변환 (casting)이다. 캐스팅 방법은 변환하고자 하는 변수나 리터럴 앞에 타입을 붙여주기만 하면 된다.
double d = 3.14;
int pi = (int)d // double 타입 변수 d를 int 타입으로 형변환
프리미티브 타입에서 boolean 을 제외한 나머지 타입들은 서로 형변환이 가능하며, 프리미티브 타입과 레퍼런스 타입 간 형변환은 불가능하다. 주의해야 할 점은 범위가 큰 타입에서 작은 타입으로 형변환할 경우 값 손실이 발생할 수 있다는 것이다.
이렇게 변환하고자 하는 타입을 명시적으로 밝혀주는 타입 캐스팅 외에 자동으로 변환해주는 타입 프로모션이 있다. 작은 범위에서 큰 범위로 형변환하는 경우 타입을 명시하지 않아도 컴파일러가 자동적으로 추가한다.
float f = 1234; // float f = (float)1234; 와 동일
char ch = 1000; // char ch = (char)1000; 과 동일
1차 및 2차 배열 선언하기
배열은 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것이다. 변수를 5개 생성하는 것과 크기가 5짜리인 배열을 생성하는 것의 차이점은 무엇일까? 메모리에 차지하는 공간은 같지만, 변수와 달리 배열은 각 저장 공간이 연속적으로 배치된다.
배열은 두 가지 방법으로 선언할 수 있는데 보통 첫 번째 방법을 선호한다.
- 타입[] 변수이름;
- ex) int[] score;
- 타입 변수이름[];
- ex) int score[];
"배열을 선언한다"라는 것은 단지 생성된 배열을 다루기 위한 참조변수의 공간만 만드는 것이다. 배열을 생성해야만 실질적인 값을 저장할 수 있는 공간이 만들어진다. 참고로 자바에서는 길이가 0인 배열도 생성할 수 있다고 한다.
int[] score; // 배열 선언
score = new int[5]; // 배열 생성
int[] score = new int[5]; // 배열의 선언과 생성을 동시에
int[] score = {10, 20, 30, 40, 50}; // 배열의 생성과 초기화를 동시에
int[][] score = new int[2][3]; // 2차원 배열
int[][] score = {
{10, 20, 30},
{40, 50, 60}
};
타입추론, var
타입추론이란 프로그래머가 변수의 타입을 명시적으로 적어주지 않아도 컴파일러가 알아서 변수의 타입을 골라주는 것이다. 사실 자바를 거의 사용해보지 않았고, 쓰더라도 java 8만 사용해봤기 때문에 타입추론이 가능할 것이라고는 상상도 못했다. var 는 자바스크립트나 코틀린에서 많이 쓰는데, 자바에서는 초기화값이 있는 지역변수로만 선언 가능하다고 한다.
var x; // (X)
var x = null; // (X)
private var x = "hello"; // (X)
var x = "hello"; // (O)