본문 바로가기
Programming/Java

[Java] 2. 데이터 타입과 형변환

by Rayched 2022. 9. 21.

Data Type, 데이터 타입의 사전적인 정의를 말하자면

'프로그래밍 언어에서 정수, 실수, 문자, 논리 등의 여러 종류의 데이터를 식별하는 분류'라고 볼 수 있다.

자바에서는 데이터 타입을 크게 '기본형'과 '참조형'으로 구분한다.

제일 먼저 기본형 데이터타입에 대해 알아보자.


기본형 Primitive Type

기본형 타입은 변수에 담는 데이터에 종류에 따라 

각각 '정수형', '실수형', '문자형', '논리형'으로 구분할 수 있다.


① 정수형

- 정수 형태의 데이터를 저장할 수 있는 데이터 타입을 말한다.

- 대표적인 정수형으로 'byte', 'short', 'integer', 'long'이 존재한다.

- 여기서 크기란 변수 선언 시에 메모리에 할당되는 공간의 크기를 의미한다.

  int 변수를 선언하면 메모리에 4 byte, 32 bit 크기의 공간이 할당이 된다.

종류 크기 값의 표현 범위 입력 예시
byte 1 byte (8 bit) -128 ~ +127 byte a = 5;
short 2 byte (16 bit) -32,768 ~ +32,767 short b = 10;
integer 4 byte (32 bit) -2,147,483,648 ~ +2,147,483,647  int c = 15;
long 8 byte (64 bit) -9,223,372,036,854,775,808 ~
+9,223,372,036,854,775,807
long d = 20;

② 실수형

- 실수 형태의 데이터를 저장할 수 있는 데이터 타입을 말한다.

- 대표적인 실수형으로는 'float'와 'double' 두 가지가 존재한다.

- 수학에서 실수는 정수도 포함하는 개념이므로, 프로그래밍에서도 정수형 데이터도 저장할 수 있다.

- 자바에서 일반적인 실수는 'double'형이다.

  따라서 float형에 실수를 저장할 때는 숫자 뒤에 'f'를 붙여서 해당 실수가 float 형태라는 것을 명시해줘야 한다.

종류 크기 값의 표현 범위 입력 예시
float 4 byte (32 bit) ±3.4 * 10^(-37) ~ ±3.4 *  10^(38) float a = 32.85f;
double 8 byte (64 bit) ±1.7 * 10^(-307) ~ ±3.4 * 10^(308) double b = 35.6;

 

③ 문자형

- 문자 형태의 데이터를 저장할 수 있는 데이터 타입을 말한다.

- character형 하나만 사용할 수 있고, character 문자형은 한 개의 문자만 저장할 수 있다.

- 문자를 저장할 때는 저장할 문자 앞에 ' '(작은따옴표)를 붙여서 저장한다.

 

④ 논리형

- 참/거짓 형태로 사용할 수 있는 데이터 타입

- 자바에서 참과 거짓은 각각 'true'와 'false'로 표현된다.

- 논리형 데이터 타입으로는 'boolean' 형이 존재한다.

종류 데이터 크기 표현 내용 입력 예시
character 2 byte (16 bit) 문자 (한 글자) char c = 'R';
boolean 1 bit 참 / 거짓 (true / false) boolean d = true; 
boolean d = false;

기본형 데이터 타입의 정의와 종류까지 알았으니, 이제 참조형에 대해 알아보자.

 

 

데이터 타입 중 하나인 '참조형'이란

값이 저장된 주소를 저장하는 자료형으로, 자바에서는 모두 객체의 주소를 의미한다.

참조형의 종류로는 'Class Type', 'Interface Type', 'Array Type', 'Enum Type'이 존재한다.

해당 참조형들의 상세한 설명은 추후에 더 자세하게 설명하도록 하고, 그냥 참조형이란 것이 있다 정도로 하고 넘어가자.


우리가 프로그래밍을 하다 보면 변수의 데이터 타입을 다른 타입으로 바꿔야 할 때가 있을 것이다.

이때 활용되는 것이 '형변환'이다.


형 변환 Type Conversion

변수의 데이터 타입을 다른 데이터 타입으로 변환하는 것을 말한다.

변환하는 방식에 따라 자동형 변환과 수동형변환으로 나뉜다.


① 자동형변환

- 변환하려는 타입을 적지 않아도, 데이터 타입이 자동으로 변환되는 형변환을 의미한다.

  타입을 따로 명시하지 않기 때문에 '묵시적 형변환'이라고 불린다.

- 데이터 크기가 작은 타입을 큰 타입으로 변환하려고 할 때 주로 사용된다.

class Main {
	public static void main(String[] args){
    	double d =10;
        //double형 변수 d를 선언하고 정수 값 10을 저장
        //double은 실수형 데이터 타입이므로 정수 10은 
        //실수 10.0으로 자동으로 형변환되어 저장된다.
        System.out.println(d);
        //출력 값: 10.0
        //자동형변환이 정상적으로 진행된 것을 확인할 수 있다.
    }
}

 

② 수동형변환

- 개발자가 변수의 형태를 지정해서 원하는 데이터 타입으로 변환하는 형변환

   데이터 타입을 명시해주기 때문에 '명시적 형변환'이라고 불린다.

- 데이터 크기가 더 큰 타입을 작은 타입으로 바꾸려고 할 때 사용된다.

class Main {
	public static void main(String[] args){
    	double d = 14.95;
        //double형 변수 d를 선언, 실수 14.95를 저장한다.
        int i = (int)d;
        //int형 변수 i를 선언하고, 변수 i에 변수 d의 값을 저장한다.
        //변수 d는 실수형이고, 변수 i는 정수형이다.
        //그냥 집어넣으면 컴파일 오류가 발생하기 때문에
        //시스템에 변수 d를 int형이라고 명시를 해줘야한다.
        //수동으로 double형에서 int형으로 형변환을 해줘야한다.
        //다만 수동형변환은 데이터 크기가 큰 타입에서 작은 타입으로 강제 형변환을 하기 때문에
        //값 손실이 발생하게 된다.
        System.out.println(i);
        //출력 값이 14.95가 아닌, 14로 출력되는 것을 확인할 수 있다.
    }
}

 

자동형변환과 수동형변환의 정의에 대해 알았으니

예시 코드를 활용해서 앞에서 공부했던 내용을 다시 정리해보겠다.

//문제 1: 수동형변환, 자동형변환 과정을 서술하시오.

public class Main {
    public static void main(String[] args) {
        //자동형변환
        //1번: 정수형 간의 형변환
        byte Cyclone = 127; //byte형 변수 Cyclone 선언, 정수 값 127을 저장한다.
        int Heat = Cyclone; //int형 변수 Heat를 선언, byte형 변수 Cyclone을 저장한다.

        System.out.println("=== 자동형변환 예시 시작 ===");
        System.out.println(Heat); //출력 값: 127
        
        //2번: 정수형 - 실수형 간 형변환
        int Luna = 12; //int형 변수 Luna 선언, 정수 12를 저장한다.
        float Joker = Luna; //float형 변수 Joker에 int형 변수 Luna를 저장한다.
        System.out.println(Joker); //출력 값: 12.0
        System.out.println("=== 자동형변환 예시 종료 ===");

        //수동형변환
        //3번: 정수형 간 형변환 2
        int Metal = 265; //int형 변수 Metal 선언, 정수 265를 저장한다.
        //byte Trigger = Metal; (X)
        byte Trigger = (byte)Metal; //byte형 변수 Trigger를 선언, 변수 Metal을 byte형으로 형변환해서 저장한다.
        System.out.println("=== 수동형변환 예시 시작 ===");
        System.out.println(Trigger); //출력 값: 9
        
        //4번: 정수형 - 실수형 간 형변환 2
        float Fang = 16.85f; //float형 변수 Fang 선언, 실수 16.85를 저장한다.
        int Accel = (int)Fang; //int형 변수 Accel 선언, 변수 Fang을 int형으로 수동형변환해서 저장한다.
        System.out.println(Accel); //출력 값: 16
        System.out.println("=== 수동형변환 예시 종료 ===");
    }
}

해당 코드를 실행하면 Console 창에 아래와 같은 출력 결과가 나오는 것을 확인할 수 있을 것이다.

프로그램 실행 결과

이제 각 문제 별로 왜 이런 결과가 나왔는지 생각을 해보자.

 

① 자동형변환 1번

(1). byte Cyclone = 127;

- byte형 변수 Cyclone을 선언하고, 정수 127을 저장한다.

- Cyclone의 현재 값: 127

- 127은 byte형에 담을 수 있는 최대 값이다 (-128 ~ 127)

 

(2). int Heat = Cyclone;

- int형 변수 Heat를 선언하고, Cyclone의 현재 값을 저장한다.

- 여기서 byte형의 데이터 크기는 1 byte, int형의 데이터 크기는 4 byte로

  byte형에서 int형으로 형변환을 할 때 값 손실이 발생하지 않는다.

- 따라서 프로그램을 실행하면 byte형 변수 Cyclone은 int형으로 자동형변환된 다음 저장된다.

- 출력 값: 127


② 자동형변환 2번

(1). int Luna = 12;

- int형 변수 Luna 선언, 정수 12를 저장한다.

- Luna의 현재 값: 12

 

(2). float Joker = Luna;

- float형 변수 Joker를 선언하고, Luna의 현재 값을 저장한다.

- float형은 4 byte의 크기를 가진 실수형 데이터 타입이고, int형은 4 byte의 크기의 정수형 데이터 타입이다.

  정수에서 실수로 변환될 때는 값의 손실이 발생하지 않기 때문에 프로그램을 실행하면

  int형 변수 Luna가 float형으로 자동형변환되어, float형 변수 Joker에 저장된다.

- 이때 Luna에 담겨있던 정수 12는 실수 12.0으로 변환된다.

- 출력 값: 12.0


③ 수동형변환 1번

(1). int Metal = 265;

- int형 변수 Metal 선언, 정수 265를 담는다.

- 현재 값: 265

 

(2). byte Trigger = Metal; (x)

- byte형 변수 Trigger 선언,  Metal의 현재 값을 저장한다.

- 프로그램을 실행하면 컴파일 오류가 발생한다.

  데이터가 큰 타입에서 작은 타입으로 형변환을 할 때는 값의 손실이 발생한다.

  자바에서는 값의 손실이 발생하는 것을 위험하다고 판단하기 때문에 데이터가 큰 타입을 작은 타입으로 자동형변환을 해주지 않는다.

  그렇기 때문에 4 byte의 데이터 크기를 가진 int형 변수 Metal을

  더 작은, 1 byte의 데이터 크기인 byte형으로 형변환하려는 해당 코드는 잘못된 것이고

  컴파일 과정에서 오류가 발생하는 것은 당연한 것이다.

 

(3). byte Trigger = (byte)Metal;

- byte형 변수 Trigger를 선언하고, int형 변수 Metal을 저장한다.

  여기서 변수 Metal이 byte형이라고 명시했으므로 프로그램을 실행하면 컴파일 오류가 발생되지 않는다.

- 다만 데이터가 큰 타입에서 작은 타입으로 변환하는 과정에서 값의 손실이 발생하게 된다.

- 출력 값: 9


④ 수동형변환 2번

(1). float Fang = 16.85f;

- float형 변수 Fang을 선언하고, 실수 16.85를 저장한다.

- 자바에서 일반적인 실수는 double형이다. 따라서 float형에 실수 값을 저장할 때는 실수 뒤에 'f'를 붙여서

  해당 실수가 float형이라는 것을 명시해줘야 한다.

- 현재 값: 16.85

 

(2). int Accel = (int)Fang;

- int형 변수 Accel을 선언하고, int형이라고 명시한 변수 Fang의 현재 값을 저장한다.

- 출력 값: 16

  float형에서 int형으로 형변환되는 과정에서 값의 손실이 발생했다.

- 수학적으로 '정수'는 실수에 포함되는 개념이다.

  프로그래밍에서도 이와 마찬가지로 정수형에서 실수형으로 변환할 때는 값의 손실이 발생하지 않지만

  반대로 실수에서 정수로 변환할 때는 값의 손실이 발생하게 된다.

  따라서 float형 변수 Fang을 int형으로 형변환하는 과정에서 원래 가진 실수 값도 정수로 변환되는데

  여기서 값의 손실이 발생하게 된다.

  그러므로 출력 값이 정수 16으로 나온 것은 정상적인 결과라고 보면 될 것이다.  

 

'Programming > Java' 카테고리의 다른 글

[Java] 4. 조건문  (1) 2022.10.05
[Java] 3. 연산자  (0) 2022.09.23
[Java] 1. 변수와 상수  (0) 2022.09.13
[Java] 0 - (1). 객체 지향 프로그래밍이란 무엇인가  (2) 2022.09.13
[Java] 0. 자바 개요  (0) 2022.08.19