본문 바로가기
Language/Java

5분 안에 자바(Java) 변수(variable) 완벽 이해하기

by 도뎡 2023. 8. 17.
반응형

1. 변수(variable)란?

프로그래밍 언어에서 변수는 데이터(data)를 저장할 수 있는 메모리상의 공간을 의미합니다. 변수에는 데이터 타입(정수, 실수, 문자, 문자열, 참/거짓 등)과 일치하는 단 하나의 값만 저장할 수 있는데요.

 

프로그래밍 언어에서 변수는 데이터(data)를 저장할 수 있는 메모리상의 공간을 의미합니다. 변수에는 데이터 타입에 해당되는 단 하나의 값만 저장할 수 있습니다.

자바의 데이터 타입은 크게 '기본형'과 '참조형'으로 나뉘며, 두 가지 모두를 통틀어 '자료형(data type)'이라고 표현합니다.

 

  • 기본형(primivite type) : 주로, 어떠한 값에 대한 연산이 필요한 경우 사용합니다. 계산기를 예로 들면, 사칙연산에 기본형 변수를 이용할 수 있습니다. 기본형의 개수는 총 8개입니다.
  • 참조형(reference type) : 8개의 기본형을 제외한 모든 타입을 의미합니다. 기본형은 실제 연산에 필요한 값을 변수에 직접 저장하는 반면, 참조형은 '객체'의 주소(memory address)를 변수에 저장합니다.

 

1-1) 기본형 (primivite type)

아래 표는 자바에서 제공하는 8가지 기본형의 종류입니다. 프로그램의 성격에 따라 다를 수 있지만, 보통 논리형인 boolean과 정수형의 int가 연산에 가장 많이 사용됩니다.

지금은 모든 자료형을 외우실 필요는 없고, 타입과 크기 정도만 훑어보고 넘어가 주시면 되겠습니다.

  타입 크기 데이터 표현(저장) 범위 기본값 사용 빈도
논리형 boolean 1 byte true 또는 false false
문자형 char 2 byte
(유니코드)
0 ~ 65,535 '\u0000'
정수형



byte 1 byte -128 ~ 127 0
short 2 byte -32,768 ~ 32,767 0
int 4 byte -2,147,483,648
~
2,147,483,647
0
long 8 byte -9,223,372,036,854,775,808
~
9,223,372,036,854,775,807
0L
실수형

float 4 byte 1.4E-45 ~ 3.4E38
(1.4×10^-45 ~ 3.4×10^38)
0.0F
double 8 byte 4.9E-324 ~ 1.8E308
(4.9×10^-324 ~ 1.8×10^308)
0.0

 

아래 코드는 8개의 기본 자료형에 해당되는 값을 변수에 저장해 출력하는 예시 코드입니다.

public class PrimiviteTypeTest {
    public static void main(String[] args) {
        boolean booleanValue = true;
        char charValue = 'A';
        byte byteValue = 127;
        short shortValue = 32767;
        int intValue = 2147483647;
        long longValue = 9223372036854775807L;
        float floatValue = 30.333F;
        double doubleValue = 99.999;

        System.out.println("charValue : " + charValue);
        System.out.println("byteValue : " + byteValue);
        System.out.println("shortValue : " + shortValue);
        System.out.println("intValue : " + intValue);
        System.out.println("longValue : " + longValue);
        System.out.println("floatValue : " + floatValue);
        System.out.println("doubleValue : " + doubleValue);
    }
}

 

각 자료형에 해당되는 값이 출력된 결과는 다음과 같습니다.

8개 기본형 - 변수 출력 결과

 

1-2) 참조형 (reference type)

아래 코드의 Member와 MemberTest는 참조형 변수를 테스트하기 위해 생성한 클래스입니다. 앞서 말씀드렸듯이, 참조형은 8개의 기본형을 제외한 모든 타입(클래스, 인터페이스 등)을 의미합니다.

참조형 변수에는 "null 또는 '객체'의 주소(4 byte 정수)"를 저장할 수 있습니다. null은 참조형 변수에 어떠한 주소도 저장되어 있지 않음을 의미하며, null인 참조형 변수는 메모리에 할당되지 않습니다.

public class Member {
    int age = 20;
    int height = 180;
    int weight = 80;
}

public class MemberTest {
    public static void main(String[] args) {
        Member member = new Member();
        System.out.println("member : " + member);
        System.out.println("age : " + member.age);
        System.out.println("height : " + member.height);
        System.out.println("weight : " + member.weight);
    }
}

 

참조형 변수는 실제 데이터가 저장된 주소(memory address)를 저장하기 때문에, member에는 Member 클래스로부터 생성된 '객체'의 주소가 저장되며, member의 실제 데이터는 메모리의 힙(heap) 영역에 저장되고, 주소값은 메모리의 스택(stack) 영역에 저장된다는 점입니다.

이때, member는 스택(stack)에 저장된 '객체'의 주소값을 통해 힙(heap)에 저장된 실제 값에 접근할 수 있습니다. 참조형 변수는 추후 객체 지향 프로그래밍을 공부하는 단계에서 자세히 알아보겠습니다.

참조형 - 변수 출력 결과

 

2. 변수의 선언

당연한 이야기지만, 변수를 사용하려면 코드 내에 반드시 변수를 선언해 주어야 합니다. 변수를 선언하는 방법은 크게 두 가지가 있습니다.

 

2-1. 변수를 초기화하지 않고, 선언만 하는 방법

아래 코드에서 'int'는 데이터를 저장할 타입을, 'age'는 변수의 이름을 의미합니다. 여기서 포인트는 age를 선언하기만 하고 값을 '초기화' 하지 않았다는 건데요. 여기서 '초기화'란 변수에 값을 저장하는 행위, 즉 변수를 사용하기 전에 값을 저장(세팅)하는 것을 뜻합니다.

int age; // 정수 타입의 데이터를 저장할 변수 age 선언


변수를 선언하면, 메모리의 빈 공간에 변수(age)의 데이터 타입(int)에 해당되는 크기만큼의 공간이 할당됩니다. 이때, 변수를 초기화하지 않으면 할당된 메모리 공간에 알 수 없는 쓰레깃값(garbage value)이 들어갈 수 있으므로, 웬만해서는 값을 초기화해 주는 습관을 들이는 것이 좋습니다.

추가적으로, 값이 초기화되지 않은 변수를 사용하게 되면 자바 컴파일러가 오류를 발생시킵니다.

 

2-2. 변수를 선언함과 동시에 초기화하는 방법

아래 코드는 정수(int) 타입의 데이터를 저장할 변수 age를 선언하는 과정에서 값을 30으로 초기화하는 코드입니다. 변수에 값을 저장할 때는 대입 연산자(' = ')를 이용하면 되는데요. '변수명 = 저장할 값;'과 같이 변수명이 좌측에, 저장할 값이 우측에 위치해야 합니다.

int age = 30; // 정수 타입의 변수 age를 선언함과 동시에 값을 30으로 초기화

 

아래 코드는 다양한 변수 선언 방법의 예시입니다. 같은 타입의 변수는 b와 c처럼 콤마(' , ')를 기준으로 한 줄에 선언할 수도 있고, 선언되기만 한 변수의 값을 후에 초기화할 수도 있으며, 변수에 이미 저장되어 있는 값을 다른 값으로 변경할 수도 있습니다.

int a = 30;         // 정수 타입의 변수 age를 선언함과 동시에 값을 30으로 초기화
int b, c;           // 정수 타입의 데이터를 저장할 변수 b, c 선언
int d = 0, e = 10;  // 정수 타입의 변수 d, e를 선언함과 동시에 값을 각각 0, 10으로 초기화
b = 10;             // b의 값을 10으로 초기화
c = 20;             // c의 값을 20으로 초기화
a = 50;             // a의 값을 30에서 50으로 변경 (기존에 저장된 값(30)은 사라짐)

 

여기서 주의해야 할 점이 하나 있는데요. 위 코드에서 d와 e처럼 변수를 선언하는 과정에서 값을  초기화하는 건 가능하지만, b와 c처럼 선언되기만 한 변수는 동시에 초기화할 수 없다는 점입니다.

// 올바른 코드 (O)
int a = 10, b = 20;

// 잘못된 코드 (X)
int a, b;
a = 10, b = 20;

// 올바른 코드 (O)
int a, b;
a = 10;
b = 20;

 

3. 변수 명명 규칙(naming rule, naming convention)

자바에는 변수의 이름을 지을 때 반드시 지켜야 하는 규칙과, 개발자들 사이에서 암묵적으로 권장하는 규칙이 존재합니다.

 

3-1) 필수 규칙

  • 변수명은 영어(대소문자), 숫자, 언더스코어(' _ '), 달러(' $ ')로만 구성해야 합니다.
  • 변수명에는 공백(' ')을 포함할 수 없습니다.
  • 자바에서 미리 정의된 예약어는 사용할 수 없습니다.
    - 예약어는 키워드(keyword)라고도 칭하며, 쉽게 말해 자바 프로그래밍에 사용되는 기본 단어를 뜻합니다.
    - ex: (int, long, if, else, for, true, false, new, null, return, void, try, this 등)

 

3-2) 권장 규칙

  • 변수명의 첫 글자는 영어 소문자로 시작해야 합니다.
  • 변수명이 여러 단어로 이어지는 경우, 제일 앞 첫 글자를 제외한 나머지 단어의 첫 글자는 대문자로 구성해야 합니다.
    - ex: (회원 아이디 : memberId, 회원명 : memberName, 회원 이메일 주소 : memberEmail)
  • 상수명은 모두 영어 대문자로 구성해야 하며, 여러 단어로 이어지는 경우 언더스코어(' _ ')로 구분해야 합니다.

 

4. 상수(constant)와 리터럴(literal)

상수도 변수와 마찬가지로 데이터를 저장할 수 있는 메모리 공간입니다. 변수는 한번 값을 저장한 후에 다른 값으로 변경이 가능하지만, 상수는 한번 값을 저장하면 다른 값으로 변경이 불가능합니다.

 

4-1) 상수

상수는 선언하는 시점에 반드시 값을 초기화해야 하며, 자바에서는 상수를 선언할 때, 아래 코드와 같이 자료형 앞에 'final' 키워드를 붙여주면 됩니다.

// 상수 선언 예시
final int HEIGHT = 180;
final int WEIGHT = 75;
final int FOOT_SIZE = 270;

 

4-2) 리터럴

리터럴은 변수 또는 상수에 저장된 값 자체를 의미합니다. 위 코드를 기준으로 HEIGHT, WEIGHT, FOOT_SIZE는 '상수'라 표현하고, 상수의 값인 180, 75, 270은 '리터럴'이라 표현합니다.

 

4-3) 상수를 사용하는 이유

상수는 절대로 변하지 않는 고정적인 값 또는 여러 곳에서 공통으로 사용되는 경우에 유용하게 쓰이는데요. 예시로, 매장에서 고객에게 문자 메시지를 전송하는 샘플 코드를 작성해 보겠습니다.

    void 첫방문_감사_메시지_전송() {
        int point = 100;
        String receiver = "010-1111-1111";
        String message = "첫방문 감사드립니다.";
        System.out.println("문자 발송");
        point = point - 3;
    }

    void 상품_구매_메시지_발송() {
        int point = 100;
        String receiver = "010-2222-2222";
        String message = "상품 구매 감사드립니다.";
        System.out.println("문자 발송");
        point = point - 3;
    }

    void 상품_환불_메시지_발송() {
        int point = 100;
        String receiver = "010-3333-3333";
        String message = "상품 환불 안내입니다.";
        System.out.println("문자 발송");
        point = point - 3;
    }

 

코드를 설명드리기 전에, 각 변수의 역할은 다음과 같습니다.

  • point : 문자 발송에 필요한 포인트 (문자를 발송할 때마다 3개씩 차감)
  • receiver : 문자 메시지를 수신받을 고객의 휴대폰 번호
  • message : 고객에게 발송할 문자 내용

 

세 개의 예시 코드 모두, 상황에 따라 고객에게 문자를 발송하는 기능을 합니다. 결론부터 말씀드리자면, 세 개 코드에서 상수로 선언해서 사용할 수 있는 값은, 문자를 발송할 때 차감되는 포인트의 개수(3) 뿐입니다.

point는 매장별로 보유 중인 개수가 다르기 때문에 상수가 될 수 없습니다. receiver도 고객마다 유동적으로 처리되어야 하고, message 또한 상황별로 다른 내용이 발송될 수 있습니다.

아래 코드는, 차감되는 포인트의 개수(3)를 상수로 선언해서 사용하는 새로운 샘플 코드입니다.

    // 문자 발송 시 차감할 포인트
    final int DEDUCT_POINT = 3;


    void 첫방문_감사_메시지_전송() {
        int point = 100;
        String receiver = "010-1111-1111";
        String message = "첫방문 감사드립니다.";
        System.out.println("문자 발송");
        point = point - DEDUCT_POINT;
    }

    void 상품_구매_메시지_발송() {
        int point = 100;
        String receiver = "010-2222-2222";
        String message = "상품 구매 감사드립니다.";
        System.out.println("문자 발송");
        point = point - DEDUCT_POINT;
    }

    void 상품_환불_메시지_발송() {
        int point = 100;
        String receiver = "010-3333-3333";
        String message = "상품 환불 안내입니다.";
        System.out.println("문자 발송");
        point = point - DEDUCT_POINT;
    }


문자 발송 시 차감되는 포인트가 3개에서 2개로 변경되었다고 가정해 보겠습니다. 만약 샘플 코드와 유사한 기능을 하는 코드가 100개가  있고, 포인트 차감 로직에 상수(DEDUCT_POINT)가 아닌 숫자 3이 코드마다 들어가 있다면, 100개의 코드를 모두 수정해야 하는 번거로운 상황이 발생할 수 있습니다.

하지만 DEDUCT_POINT와 같이 상수로 처리했을 땐, 상수의 값(리터럴)만 변경해 주면 단 한 줄의 코드로 해당 상수가 사용된 모든 코드를 처리할 수 있는 유연한 구조를 만들 수 있습니다.

이처럼, 변하지 않는 고정적인 값, 변동성이 적은 값, 그리고 여러 곳에서 공통으로 사용되는 값은 상수로 처리해 주시면 됩니다.

반응형

댓글