언어(Language)/Java

[Java] 자바의 데이터 타입 종류와 데이터 타입 변환

잇트루 2022. 9. 5. 19:26
반응형

정수형 (byte, short, int, long)

정수형 데이터 타입은 숫자를 나타내는 자료형으로 byte, short, int, long이 있다. 이들은 각각 차지하는 메모리의 크기와 나타낼 수 있는 숫자의 범위가 다르다.

과거에는 메모리의 용량이 크지 않아서, 필요에 따라 변수의 범위를 알맞게 사용해야 했다. 그로 인해 가장 적은 메모리를 사용하는 byte(1byte)부터 가장 많은 메모리를 차지하는 long(8byte)까지 정수를 표현하는 것에도 다양한 데이터 타입이 쓰이게 된 것이다.

하지만, 현대에는 메모리의 용량이 부족할 일이 거의 없기 때문에, 일반적으로 int형을 주로 사용한다.

 

정수형 데이터 타입의 메모리와 범위는 다음과 같다.

자료형 메모리 범위
byte 1byte -128 ~ 127 (-2^7 ~2^7 - 1)
short 2byte -32,768 ~ 32,767 (-2^15 ~ 2^15 - 1)
int 4byte -2,147,483,648 ~ 2,147,483,647 (-2^31 ~ 2^31 - 1)
long 8byte -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 (-2^63 ~ 2^63 - 1)

 

정수형 리터럴은 다음과 같이 정수형 변수에 할당할 수 있다.

// 정수형 변수의 올바른 리터럴 할당
byte byteNumber = 123;
short shortNumber = 12345;
int intNum = 123456789;
long longNumber = 12345678910L;

short shortNumber = 12_345;
int intNum = 123_456_789;
long longNumber = 12_345_678_910L;

 

데이터 타입의 범위를 넘는 리터럴은 에러가 발생한다.

// 정수형 변수의 잘못된 리터럴 할당
byte byteNumber = -130;
short shrotNumber = 123456;
int intNumber = 2147483648;

 

정수형 리터럴을 사용할 때 주의할 점

long 타입의 변수에 정수형 리터럴을 할당할 때, 접미사 L을 붙여주어야 한다.

long bigNumber = 123456789123L;

 

정수형의 오버플로우와 언더플로우

 

오버플로우

정수형 오버플로우는 자료형이 표현할 수 있는 범위 중 최댓값을 벗어날 경우 발생한다. 이 때, 최댓값을 초과하는 경우, 해당 타입의 최솟값으로 순환한다.

byte num = 127;
system.out.println(++num);
// 출력 결과 : -128

 

언더플로우

정수형 언더플로우는 자료형이 표현할 수 있는 범위 중 최솟값을 벗어날 경우 발생한다. 이 때, 최솟값을 초과하는 경우, 해당 타입의 최댓값으로 값이 순환한다.

byte num = -128;
system.out.println(--num);
// 출력 결과 : 127

 

실수형 (float, double)

실수는 소수점을 가지는 값이다. 자바에서 실수를 나타내는 데이터 타입은 float형과 double형 두 가지로 분류된다.

자료형 메모리 범위 정밀도
float 4byte 음수 : -3.4 * 10^38 ~ -1.4 * 10^-45
양수 : 1.4 * 10^-45 ~ 3.4 * 10^38
7자리
double 8byte 음수 : -1.8 * 10^308 ~ -4.9 * 10^-324
양수 : 4.9 * 10^-324 ~ 1.8 * 10^308
15자리

 

실수형 리터럴은 다음과 같이 실수형 변수에 할당할 수 있다.

float pi = 3.14f;

double pi = 3.14;
double pi = 3.14d;

컴퓨터에서는 실수를 저장할 때, 부동소수점 표현 방식으로 저장한다. 부동소수점 표현 방식은 효율적인 방식이지만, 약간의 오차가 발생할 때가 있다.

따라서, 4byte 메모리를 차지하는 float형보다 8byte 메모리를 차지하는 double형이 정밀도가 더 높다.

 

실수형 리터럴을 사용할 때 주의할 점

float 타입의 변수에 실수형 리터럴을 할당할 때, 접미사 f을 붙여주어야 한다. double 타입 또한 접미사 d를 붙여 표현이 가능하지만, 일반적으로 생략하여 사용한다.

float pi = 3.14f;

 

실수형의 오버플로우와 언더플로우

실수형에서도 오버플로우와 언더플로우가 발생한다. 하지만, 오버플로우와 언더플로우가 발생했을 때의 결과가 다르니 사용할 때 주의해야 한다.

오버플로우

값이 음의 최소 범위 또는 양의 최대 범위를 넘어갔을 때 발생하며, 값은 무한대가 된다.

 

언더플로우

값이 음의 최대 범위 또는 양의 최소 범위를 넘어갔을 때 발생하며, 값은 0이 된다.

 

논리형 (boolean)

자바에서 논리형 데이터 타입은 boolean형이 있다. boolean형은 참(true) 또는 거짓(false)을 저장할 수 있는 데이터 타입으로, true 또는 false를 값으로 가진다. 따라서 조건문 또는 반복문(while)과 함께 자주 사용된다.

boolean isJava = true;
boolean isPython = false;

단순 참과 거짓만을 표현하기 때문에 1bit만 있으면 되지만, JVM에서 실행되기 위해서는 데이터의 최소 단위가 1byte로 boolean형은 1byte의 크기를 가진다.

 

문자형 (char)

자바에서의 문자형 데이터 타입은 2byte 크기의 char형이 있다. char형은 해당 변수의 단 하나의 문자형 리터럴만을 저장할 수 있다.

문자형 리터럴을 작성할 때에는 반드시 작은 따옴표(’’)를 사용해야 한다. 자바에서는 문자형(char)과 문자열은 다르게 사용되기 때문에, 큰 따옴표(””)를 사용한 리터럴은 문자열 리터럴로 인식되므로 주의해야 한다.

// char형의 올바른 사용
char ch1 = 'a';
char ch2 = 'b';

// char형의 잘못된 사용
char ch3 = 'ab'; // 단 하나의 문자형 리터럴만 할당 가능
char ch4 = "a";  // 작은 따옴표를 사용해야 함

자바에서 문자는 유니코드 문자를 사용하여 저장한다. 유니코드는 컴퓨터에서 문자를 표현하는 여러 방식 중 국제 표준으로 사용되는 코드이다. 각 문자에 코드 번호를 부여한 것으로 코드 번호를 사용한다. 예를 들어 ch1 문자형 변수에 ‘a’라는 문자형 리터럴을 할당할 시, 유니코드 상의 a에 해당하는 코드 번호가 저장되는 것이다.

 

따라서 문자형 변수에 숫자를 할당하여 사용할 수 있다. char형에 숫자를 할당하면, 숫자 값을 유니코드로 인식하여 유니코드 상에 해당하는 코드 번호와 일치하는 문자로 변환하여 저장하게 된다.

public class CharEx {
    public static void main(String[] args) {
        char ch1 = 65;
        char ch2 = 97;

        System.out.println(ch1); // 'A'
        System.out.println(ch2); // 'a'
    }
}

유니코드 상에서 ‘A’는 65, ‘a’는 97을 가지고 있다. 알아두면 유용하게 사용될 것이다.

 

데이터 타입 변환

변수를 선언할 때 데이터 타입을 지정해 주어야 한다. 하지만, boolean을 제외한 기본 타입은 서로 데이터 타입을 변환할 수 있다. 데이터 타입의 변환 방식은 자동으로 데이터 타입을 변환하는 방식과 수동으로 데이터 타입을 변환하는 방식이 있다.

 

자동 데이터 타입 변환

자동으로 데이터 타입이 변환되는 조건은 두 가지가 있다.

  1. 바이트 크기가 작은 타입에서 큰 타입으로 변환할 때(byte → int → long)
  2. 덜 정밀한 타입에서 더 정밀한 타입으로 변환할 때(정수 → 실수)

이를 순서대로 나타내면 다음과 같다.

byte -> short/char -> int -> long -> float -> double

화살표 왼쪽에 있는 데이터 타입은 오른쪽에 남아 있는 데이터 타입들로 자동으로 변환될 수 있다.

 

float형의 크기는 4byte로 long형의 크기인 8byte로 작다. 하지만, 정밀도 측면에서 float가 long보다 정밀하기 때문에 자동으로 데이터 타입 변환이 가능하다.

public class TypeEx {
    public static void main(String[] args) {
        long longValue = 123L;
        float floatValue = longValue;

        System.out.println(floatValue); // 123.0 출력
    }
}

 

수동 데이터 타입 변환

차지하는 메모리 용량이 더 큰 데이터 타입에서 작은 데이터 타입으로는 자동으로 변환해 주지 않는다. 예를 들어 long형(8byte)에서 int형(4byte)으로는 자동으로 데이터 타입 변환이 안된다는 것이다. 이러한 경우, 수동으로 데이터 타입을 변환해 주어야 한다. 이를 캐스팅(casting)이라 한다.

 

수동으로 데이터 타입을 변환할 때에는 캐스팅 연산자 ’()’를 사용하여 변환한다. 캐스팅 연산자 안에는 변환할 데이터 타입을 입력한다.

public class TypeEx {
    public static void main(String[] args) {
        long longValue = 2147483648L; // int의 최대 범위보다 1 큰 값
        int intValue = (int)longValue;

        System.out.println(intValue); // 오버플로우 발생, 순환되어 -2147483648 출력
    }
}

 

문자열과 정수의 변환

정수형 데이터 타입을 문자열 클래스 타입으로(int to string), 문자열 클래스 타입을 정수형 데이터 타입으로(string to int)으로 변환이 가능하다. 단, 문자열 데이터 안에 숫자로 이루어진 문자열로 작성해야만 데이터 타입을 변환할 수 있다.

 

int to string

정수형 데이터 타입을 문자열 클래스 타입으로 변환시 Integer.toString()을 사용하여 다음과 같이 작성할 수 있다.

public class IntToStringEx{  
    public static void main(String args[]){
        // num = 정수형 데이터 타입, str = 문자열 데이터 타입
        int num = 5;
    	String str = Integer.toString(i);

    	System.out.println(num + 10); // 5 + 10 = 15
    	System.out.println(str + 10); // "5" + "10" = "510"
    }
}

 

string to int

문자열 클래스 타입을 정수형 데이터 타입으로 변환시 Integer.parseInt()를 사용하여 다음과 같이 작성할 수 있다.

public class StringToIntEx{
    public static void main(String args[]){
        // num = 정수형 데이터 타입, str = 문자열 데이터 타입
        String str = "5";
        int num = Integer.parseInt(s);

        System.out.println(str + 10); // "5" + "10" = "510"
        System.out.println(num + 10); // 5 + 10 = 15
    }
}
반응형