[Java] 02. 변수와 상수 선언법, 그리고 원시 데이터형과 클래스 데이터형의 차이


Study/Java  2020. 5. 2. 11:51

안녕하세요. 명월입니다.


이 글은 Java의 변수와 상수 선언법, 그리고 원시 데이터형과 클래스 데이터형의 차이에 대한 글입니다.


어떤 프로그램을 공부하던지 가장 처음 배우는 건 변수와 상수 선언법이지 않을까 싶습니다.

변수와 상수의 단순한 차이는 변하는 값과 변하지 않는 값의 단어적 차이가 있고 내부적으로는 같은 개념입니다. 그래서 일단 편하게 합쳐서 변수라고 표현하겠습니다.


컴퓨터는 크게 CPU와 메모리, 하드 디스크로 구성 되어 있고, 일반적인 IO 장치로는 모니터, 키보드, 마우스가 있습니다.

CPU는 연산하는 것이고 메모리와 하드 디스크는 데이터를 저장하는 곳입니다. 여기서 메모리와 하드 디스크의 차이는 프로그램을 종료 후에도 데이터가 남아있는지 아닌지의 차이입니다.

여기서 우리가 프로그램을 실행하면서 메모리를 사용하게 되는데, 이 메모리에 값을 임시(?)로 저장하는 것이 변수의 역할입니다.


이 변수 타입(Primitive type 기준)은 크게 정수형, 실수형, 문자형, 부울형으로 나눕니다.

정수형으로는 int, byte, short, long이 있고 실수형은 float, double이고 문자형은 char가 있고, 참 거짓의 구분형인 부울형은 boolean이 있습니다.

여기서 저의 경험상 자주 사용하는 자료형은 int, byte, boolean, 간혹 char가 전부입니다. 예전에는 소수점 이하를 표현하기 위해 float나 double도 사용하긴 했는데, 「부동소수점 오차」라고 버그아닌 버그가 있는데 그로 인해 계산상의 오류가 발생하는 경우가 있어 BigDecimal를 자주 사용합니다.

자료형 설명
문자 형식 데이터형
char 16비트 유니코드 문자(아스키코드 참조)
string char형식으로 이루어진 유니코드 문자열
부울 형식 데이터형
boolean 참(true), 거짓(false) 형태의 논리 데이터 처리
정수 형식 데이터형
byte -128~127
short -32,768~32,767
int -2,147,483,648~2,147,483,647
long -9,223,372,036,854,755,808~9,223,372,036,854,755,807
실수 형식 데이터형
float ±1.5*10-45~±3.4*1038
double ±5.0*10-324~±1.7*10308
decimal ±1.0*10-28~±7.9*1028

Java는 특이하게 원시 데이터 타입(Primitive type)과 클래스 타입을 구분해 놓는데 이는 int와 Integer의 변수는 다른 것이고 int는 null를 허용하지 않지만 Integer는 null를 허용하는 정수형 타입입니다.


변수 선언은 변수 타입을 앞에 쓰고 변수 명을 작성하여 선언합니다. 변수에 값을 넣을 때는 이꼴(equal, =) 기호를 사용해서 대입합니다.

public class Test {
  // 실행 함수
  public static void main(String[] args) {
    // 정수형 int, 변수명 a
    int a;
    // 실수형 float, 변수명 b
    float b;
    // 문자형 char, 변수명 c
    char c;
    // 부울형 boolean, 변수명 d
    boolean d;
    
    // 값을 넣을 때는 이꼴을 사용한다.
    // a는 정수형이기 때문에 정수 값을 넣는다.
    a = 1;
    // b는 실수형이기 때문에 실수 값을 넣는다. (여기서 float형은 f를 double형은 d를 숫자뒤에 넣는다.)
    b= 2.1f;
    // c는 문자형이기 때문에 문자 한 글자를 넣는다. (여기서 문자는 작은 따온표, 문자열은 큰따옴표로 구분. 문자열은 char 타입에 들어가지 않는다.)
    c = 'a';
    // d는 부울형이기 때문에 true, false로 값을 넣는다.
    d = true;
    
    // 콘솔 출력
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + c);
    System.out.println("d = " + d);
  }
}

여기까지 변수 타입은 원시형 데이터 타입(Primitive type)입니다.

자바에서는 조금 복잡하게 원시형 데이터 타입과 클래스형 데이터 타입이 있는데, 원시형 데이터 타입은 C/C++에서 온 잔재이고 클래스형 타입은 Java 라이브러리에서 원시형 타입을 재정의하였거나 개발자가 필요에 의해 만든 데이터 타입입니다.

이 클래스형 데이터 타입은 모두 Object 클래스를 상속받았습니다.


원시형 데이터 타입과 클래스형 타입의 차이는 null를 가질 수 있나 없나의 차이입니다.

먼저 null이란 데이터를 선언했지만 실제 메모리에는 존재하지 않는다라는 의미입니다.이게 왜 원시형 데이터 타입은 null이 불가능하고 클래스형에는 null이 가능한지의 차이입니다만 stack메모리와 heap 메모리에 대한 개념을 알고 있어야 하는 부분입니다.

나중에 new와 클래스 할당, 메모리 구조에 대해 따로 글을 작성하겠습니다. 여기서는 간단하게 클래스형 타입에는 null를 가질 수 있다라고 알고 있으면 됩니다.


클래스형 타입은 유저가 새로 작성을 할 수 있는 부분이기도 하기 때문에 대표적인 원시형 데이터 타입을 비교하여 설명하겠습니다.

정수형으로는 Integer, Byte, Short, Long이 있고 실수형은 Float, Double이고 문자형은 Character가 있고, 참 거짓의 구분형인 부울형은 Boolean이 있습니다.

추가로 문자열형은 String이 있고, BigDecimal의 문자실수형이 있습니다. 특이점은 원시형 데이터 타입은 소문자로 시작하지만 클래스형은 모두 대문자로 시작합니다.

// BigDecimal형을 사용하기 위해서 클래스를 선언해야 한다.
import java.math.BigDecimal;
public class Test {
  // 실행 함수
  public static void main(String[] args) {
    // 정수형 Integer, 변수명 a
    Integer a;
    // 실수형 Float, 변수명 b
    Float b;
    // 문자형 Character, 변수명 c
    Character c;
    // 부울형 Boolean, 변수명 d
    Boolean d;
    // 문자열형 Boolean, 변수명 e
    String e;
    // 문자실수형 BigDecimal, 변수명 f
    BigDecimal f;
    
    / 값을 넣을 때는 이꼴을 사용한다.
    // a는 정수형이기 때문에 정수 값을 넣는다.
    a = 1;
    // b는 실수형이기 때문에 실수 값을 넣는다. (여기서 float형은 f를 double형은 d를 숫자뒤에 넣는다.)
    b= 2.1f;
    // c는 문자형이기 때문에 문자 한 글자를 넣는다. (여기서 문자는 작은 따온표, 문자열은 큰따옴표로 구분. 문자열은 char 타입에 들어가지 않는다.)
    c = 'a';
    // d는 부울형이기 때문에 true, false로 값을 넣는다.
    d = true;
    // e는 문자열형이기 때문에 문자열을 넣는다.
    e = "Hello world";
    // BigDecimal은 자동 operation 변환 식이 없다. 그래서 new를 사용해야 한다.
    // 문자 실수형. 정수나 실수형으로도 대입 가능하다. 그러나 오차를 줄이기 위해서 문자열이 좋다.
    f = new BigDecimal("3.1");
    
    // 콘솔 출력
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + c);
    System.out.println("d = " + d);
    System.out.println("e = " + e);
    System.out.println("f = " + f);
  }
}

변수는 단순히 값만 넣는 것만 사용하는 것이 아니고 꺼내서 계산하여 다시 넣을 수도 있고, 문자열은 합칠 수도 있습니다.

public class Test {
  // 실행 함수
  public static void main(String[] args) {
    // 정수 선언  
    int a = 5;
    Integer b = 10;
    // a(5) + b(10)를 더하면 15가 되어 c변수에 저장
    int c = a + b;
    // 콘솔 출력
    System.out.println("a + b = " + c);
    // 문자열 선언
    String d = "Hello";
    String e = "World";
    // d(Hello)와 f(World)의 문자열이 합쳐서 HelloWorld
    String f = d + e;
    // 콘솔 출력
    System.out.println("d + f = " + f);
  }
}

이제 여기서 변수와 상수의 차이는 변수를 보면 데이터를 넣고 참조해서 다시 넣고 할 수 있습니다.

그런데 상수는 한번 데이터가 들어가면 절대 값을 바꿀 수 없는 데이터를 상수라고 합니다.

public class Test {
  // 실행 함수
  public static void main(String[] args) {
    // 일반 변수
    // 처음에 5를 넣고
    int a = 5;
    // 다음에 10을 넣고
    a = 10;
    // 15를 넣고 해도 에러가 나지 않는 변수
    a = 15;
    // 상수는 변수 앞에 final 키워드를 넣는다.
    // 10을 넣고.
    final int b = 10;
    // 15를 넣으면 에러가 발생한다.
    b = 15;
  }
}

이렇게 에러가 발생합니다.

프로그램상의 제약이기 때문에 메모리상으로 고정된 데이터가 입력되거나 수정할 수 없는 건 아닙니다.

그러다 보니 변수, 상수를 구분하여 변수 선언하는 게 사실 크게 의미가 없습니다. 실제 업무 프로그램에서도 클래스의 캡슐화를 통해서 변수의 접근 제한, 수정 제한을 설정하지 final 키워드로 변수값을 제어하는 경우는 없습니다.

C++ 시절의 전처리문의 편리성 때문에 남아있는 잔재 같은 느낌이어서 상수는 잘 몰라도 프로그램하는 데 아무 지장 없습니다.

변수를 선언하는 방법과 원시 데이터형, 클래스 데이터형의 차이는 반드시 알고 있어야 하고 클래스 형은 앞으로 클래스를 설명할 때, 좀 더 자세히 설명하겠습니다.


여기까지 Java의 변수와 상수 선언법, 그리고 원시 데이터형과 클래스 데이터형의 차이에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.