"변수란, 단 하나의 값을 저장할 수 있는 메모리 공간."
변수를 사용하려면 먼저 변수 선언이 필요하다.
int age; //age라는 이름의 변수를 선언
코드에서의 int
는 변수타입, age
는 변수이름이다.
변수를 선언하면, 메모리의 빈 공간에 '변수타입'에 알맞은 크기의 저장공간이 확보되고, 앞으로 이 저장공간은 '변수이름'을 통해 사용할 수 있게 된다.
메모리에 쓰레기 값이 남아있을 수 있기 때문에 변수를 선언하고 나서는 '초기화'해야 한다.
"변수의 초기화란, 변수를 사용하기 전에 처음으로 값을 저장하는 것"
int age = 25; //변수 age를 선언하고 25로 초기화
위의 코드의 경우, 변수의 선언과 동시에 초기화가 이루어졌다.
변수의 종류에 따라 변수의 초기화를 생략할 수 있는 경우도 있지만, 변수는 사용되기 전에 적절한 값으로 초기화 하는 것이 좋다.
(지역변수는 사용되기 전에 초기화를 반드시 해야 하지만, 클래스변수와 인스턴스변수는 초기화 생략 가능함. 자세한 내용은 6장에서)
프로그래밍에서 사용하는 모든 이름을 '식별자(identifier)'라고 하며, 식별자는 같은 영역 내에서 서로 구분될 수 있어야 한다. 식별자를 만들 때는 다음의 규칙을 지켜야 한다.
위의 규칙의 경우 틀리면 에러가 발생하기 때문에 크게 문제가 되는 부분이 아니다. 오히려 주의하고 신경써야 하는 부분은 이제부터 언급될 'Code Convention'에 대한 내용이다.
public class HelloWorld {}
class AutoVendingMachine {}
int myAge;
boolean isSingle;
public int getAge() {return 20;}
final double PI = 3.141592;
final int MAX_NUMBER = 100;
명사
여야 하고, 메소드의 경우 동사로 시작
하는 것이 일반적이다. (물론 필요에 따라 예외적인 경우도 있음)이처럼 Code Convention을 준수한다면 readablity가 높아져 코드 리팩토링에도 큰 도움을 줄 수 있다.
참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로 선언은 클래스이름 변수이름;
의 형식을 따른다. 아래의 구체적인 코드를 보자.
Date today = new Date(); //Date 객체를 생성해서, 그 주소를 today에 저장
객체를 생성하는 연산자 new의 결과는 생성된 객체의 주소이다. 이 주소가 참조형 변수 today에 저장된 것으로, 이제 today를 통해서 생성된 객체를 사용할 수 있게 된다.
기본형에는 모두 8개의 자료형이 있으며, 크게 논리형, 문자형, 정수형, 실수형으로 구분된다.
변수(variable): 하나의 값을 저장하기 위한 공간
상수(constant): 값을 한번만 저장할 수 있는 공간, 키워드 'final' 붙임
리터럴(literal): 그 자체로 값을 의미하는 것
JDK1.6부터 상수를 선언과 동시에 초기화 하지 않아도 되며, 사용하기 전에만 초기화하면 되도록 바뀜. 그래도 상수는 선언과 동시에 초기화하는 습관을 들이자.
int year = 2014; //변수(year), 리터럴(2014)
final int MAX_VALUE = 100; //상수(MAX_VALUE), 리터럴(100)
변수에 타입이 있는 것처럼 리터럴에도 타입이 있다. 논리형과 문자형의 경우 접미사는 없다.
float pi = 3.14; //에러. float타입 변수에 double타입 리터럴 저장불가
double rate = 1.618; //OK. 접미사 d는 생략할 수 있다.
리터럴에 접미사가 붙는 타입은 long, float, double뿐인데, double은 생략가능하므로 long과 float의 리터럴에 접미사를 붙이는 것만 신경쓰면 된다.
리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.
int i = 'A'; //OK. 문자 'A'의 유니코드인 65가 변수 i에 저장된다.
long l = 123; //OK. int보다 long타입이 더 범위가 넓다.
double d = 3.14f; //OK. float보다 double타입이 더 범위가 넓다.
그러나 리터럴의 값이 변수 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타입보다 저장범위가 넓으면 컴파일 에러가 발생한다.
int i = 0x123456789; //에러. int타입의 범위를 넘는 값을 저장
float f = 3.14; //에러. float타입보다 double 타입의 범위가 넓다.
값의 크기에 상관없이 double타입의 리터럴을 float타입의 변수에 저장할 수 없다는 것만 주의하자. (보다 자세한 내용은 '형변환' 파트에서,,)
작은따옴표로 문자 하나를 감싼 것을 '문자 리터럴', 큰 따옴표로 두 문자 이상을 감싼 것을 '문자열 리터럴'이라고 한다. char타입의 변수는 단 하나의 문자만 저장할 수 있으므로 문자열을 저장하기 위해서는 String타입을 사용해야 한다.
문자열 + any type -> 문자열 + 문자열 -> 문자열
덧셈 연산자(+)는 피연산자가 모두 숫자일 때는 두 수를 더하지만, 피연산자 중 어느 한 쪽이 String이면 나머지 한 쪽을 먼저 String으로 변환한 다음 두 String을 결합한다. (7+"7"의 경우 "77"의 결과를 얻음)
printf()는 '지시자(specifier)'를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력하는 기능을 가지고 있다. '지시자'는 값을 어떻게 출력할 것인지 지정해주는 역할을 한다.
Scanner 클래스를 사용하려면 import java.util.*;
가 필요하다. 그 다음엔 Scanner 클래스의 객체를 생성한 뒤 nextLine() 메서드를 이용하여 문자열을 입력받는다.
Scanner scanner = new Scanner(System.in); //Scanner 클래스의 객체 생성
String input = scanner.nextLine(); //입력받은 내용을 input에 저장
int num = Integer.parseInt(input); //입력받은 내용을 int타입 값으로 변환
사실 Scanner 클래스에는 nextInt()나 nextFloat()와 같이 따로 변환할 필요없이 숫자로 바로 입력받을 수 있는 메서드들이 있지만, 이 메서드들은 화면에서 연속적으로 값을 입력받아서 사용하기에 까다롭다. 차라리 모든 값을 nextLine()으로 입력받아서 적절히 변환하는 것이 나을 수 있다. (상황에 따라 적절한 메서드 호출하기)