학습 자료

변수 — 타입을 먼저 쓴다


Article

값을 하나 기억해두고 싶다. 이름을 붙여서 나중에 다시 꺼내 쓰려는 것이다.

public class Main {
    public static void main(String[] args) {
        age = 20;
        System.out.println(age);
    }
}

읽기에는 아무 문제가 없어 보인다. 그런데 컴파일이 안 된다.

터미널
  • Main.java:3: error: cannot find symbol
  • age = 20;
  • ^
  • symbol: variable age
  • location: class Main

age 라는 이름을 못 찾겠다고 한다. 우리는 방금 만들었는데.

자바에서 이름을 만들려면 그 이름이 어떤 종류의 값을 담을지 먼저 밝혀야 한다. 이걸 안 했으니 컴파일러 입장에서는 age 라는 이름이 세상에 존재한 적이 없다.

int age = 20;

앞에 int 한 단어가 붙었다. 이게 이번 강의의 전부다. 다만 이 한 단어가 자바라는 언어의 성격을 거의 다 설명한다.

이름 앞에 종류를 적는다

int 는 정수(integer)를 뜻한다. "age 라는 이름에는 정수만 담겠다"는 선언이다.

int age = 20;
double height = 175.5;
boolean isStudent = true;

읽는 순서는 이렇다.

int age = 20;
  1. int어떤 종류를 담을 상자인가
  2. age상자에 붙일 이름
  3. =오른쪽 값을 왼쪽에 넣는다
  4. 20넣을 값

= 는 "같다"가 아니라 "넣는다" 이다. 수학의 등호와 다르다. 이 기호를 대입 연산자라고 부른다.

한 번 선언한 뒤에는 타입을 다시 적지 않는다.

int age = 20;
age = 21;        // 값만 바꾼다
int age = 22;    // 에러 — 같은 이름을 또 선언할 수 없다
age 라는 이름의 상자

int age = 20; 을 실행한 직후

age
20
상자에는 int 만 들어갈 수 있다. 크기도 미리 정해져 있다.

선언과 초기화는 나눌 수 있다

이름만 먼저 만들어두고, 값은 나중에 넣어도 된다.

int age;          // 선언
age = 20;         // 초기화

다만 값을 넣기 전에 꺼내 쓰면 컴파일러가 막는다.

int age;
System.out.println(age);
터미널
  • Main.java:3: error: variable age might not have been initialized

"초기화가 안 됐을 수도 있다"고 한다. 빈 상자를 열어보려는 것을 컴파일러가 미리 알아챈 것이다.

이게 자바가 타입을 적으라고 시키는 대가다. 귀찮은 대신, 실행하기도 전에 실수를 잡아준다.

종류가 안 맞으면 못 넣는다

정수를 담겠다고 선언한 상자에 글자를 넣어보자.

int age = "스무살";
터미널
  • Main.java:3: error: incompatible types: String cannot be converted to int
  • int age = "스무살";
  • ^

Stringint 로 바꿀 수 없다고 한다. 화살표까지 문제 지점을 정확히 가리킨다.

이 에러는 프로그램을 실행해서 만난 게 아니다. 아직 한 줄도 실행되지 않았다. javac 가 코드를 읽다가 발견한 것이다.

이름 짓는 규칙

자바가 강제하는 규칙과, 사람들이 지키는 관례가 따로 있다.

구분내용
필수숫자로 시작할 수 없다2age ✕ · age2
필수키워드는 쓸 수 없다int ✕ · class
필수공백과 기호를 넣을 수 없다my age ✕ · my-age
관례소문자로 시작한다age ○ · Age
관례단어가 겹치면 뒤 단어를 대문자로myAge · userName
관례줄임말보다 풀어 쓴다n △ · count

관례를 어겨도 컴파일은 된다. 다만 자바를 쓰는 사람들은 거의 예외 없이 이렇게 쓴다. myAge 처럼 낙타 등 모양으로 오르내린다고 해서 카멜 케이스라고 부른다.

2강에서 클래스 이름은 대문자로 시작한다고 했다. 변수는 소문자로 시작한다. 이 차이 덕분에 코드를 보다가 Hellohello 만 봐도 클래스인지 변수인지 짐작할 수 있다.

var — 타입을 안 적어도 되는 경우

자바 10 부터는 var 를 쓸 수 있다.

var age = 20;           // int 로 정해진다
var height = 175.5;     // double 로 정해진다
var name = "김자바";     // String 으로 정해진다

편해 보이지만, 오해하기 딱 좋은 문법이다.

증거는 간단하다.

var age = 20;
age = "스무살";
터미널
  • Main.java:4: error: incompatible types: String cannot be converted to int

int 라고 적은 적이 없는데 int 라고 혼난다. 컴파일러가 이미 정해뒀기 때문이다.

var 는 값을 같이 주지 않으면 못 쓴다. 추측할 근거가 없어서다.

var age;        // error: cannot infer type for local variable age

이 시리즈에서는 당분간 타입을 손으로 적는다. 타입이 눈에 보여야 배우기 좋기 때문이다.

정리하면

자바에서는 변수를 만들 때 담을 값의 종류를 먼저 적고, 컴파일러가 그 약속을 실행 전에 검사한다.

다시 짚어보기
  1. 01

    타입을 이름 앞에 적는다

    적지 않으면 컴파일러는 그 이름을 모른다.

    int age = 20;
  2. 02

    = 는 넣는다는 뜻이다

    오른쪽 값을 왼쪽 상자에 넣는다. 같다는 뜻이 아니다.

  3. 03

    빈 상자를 열면 막힌다

    값을 넣기 전에 꺼내 쓰면 컴파일 에러다.

  4. 04

    종류가 다르면 못 넣는다

    실행 전에 잡힌다. 이게 타입을 적는 대가이자 보상이다.

    int age = "스무살";  // 컴파일 에러
  5. 05

    var 는 타입을 없애지 않는다

    컴파일러가 대신 정할 뿐, 한 번 정해지면 못 바꾼다.

그런데 int 말고 또 무엇이 있을까? 이름 앞에 적을 수 있는 단어의 목록이 있을 텐데.

다음 강의에서 그 목록을 본다. 목록은 딱 여덟 개다. 그리고 그 여덟 개에 속하지 않는 나머지 전부가 또 하나의 무리를 이룬다. 이 시리즈에서 가장 자주 되돌아올 구분이 거기서 생긴다.

변수 — 타입을 먼저 쓴다 — 디코드랩(DCODELAB)