타입 변환
자바에는 두 종류의 타입 변환이 있다.
- 자동 타입 변환 (묵시적)
- 강제 타입 변환 (명시적)
1. 자동 타입 변환
프로그램 실행 도중에 자동으로 타입 변환이 일어난다.
작은 크기 가지는 타입이 큰 크기를 가지는 타입에 저장될 때 발생한다.
큰 크기 타입 = 작은 크기 타입
타입별 크기 순서 (byte)
byte (1) < short (2) < int (4) < long (8) < float (4) < double (8) |
* float은 표현 범위가 더 크기 때문에 더 큰 타입으로 들어간다.
byte byteVal = 10;
int intVal = byteVal; // 자동 타입 변환으로 byteVal 은 int 형으로 변환된다.
(가지고 있는 값 10은 변하지 않음)
int intVal = 20;
double doubleVal = intVal; //20.0
실수 타입으로 변환되면 .0 이 붙은 실수값이 된다.
char charVal = 'A';
int intVal = charVal; //65 저장됨
char 타입이 int 타입으로 변환되면 유니코드 값이 저장된다.
단, 음수가 저장될 수 있는 byte, int 등의 타입은 char 타입으로 자동 타입 변환할 수 없다!!
byte byteVal = 65;
char charVal = byteVal; // 컴파일 에러!!
char charData = (char) byteVal; // 강제 타입 변환은 가능하다.
public class PromotionExam {
public static void main(String[] args) {
byte byteVal = 10;
int intVal = byteVal; //byte -> int
System.out.println(intVal); //10
char charVal = '가';
intVal = charVal; //char -> int
System.out.println("가의 유니코드 : "+intVal); //가의 유니코드 : 44032
intVal = 500;
long longVal = intVal; //int -> long
System.out.println(longVal); // 500
intVal = 200;
double doubleVal = intVal; //int -> double
System.out.println(doubleVal); //200.0
}
}
2. 강제 타입 변환 (Casting)
큰 크기 타입은 작은 타입으로 자동 타입 변환을 할 수 없다.
하지만 강제로 int 타입의 1 byte 를 잘라서 byte 타입 변수에 저장할 수 있다. (나머지 3byte는 버려지게 된다.)
작은 크기 타입 = (작은 크기 타입)큰 크기 타입
int intVal = 103029770; //00000110 00100100 00011100 00001010 (10이 저장됨)
byte byteVal = (byte)intVal; //강제 타입 변환
원래 값은 보존되지 못한다. (밑줄 친 비트들만 저장되기 때문!!)
만약 intVal이 1 byte 크기 내의 값을 가진다면, 값은 보존된다.
int 타입 역시 char로 자동 타입 변환되지 않기 때문에 강제 타입 변환을 사용한다.
int intVal = 'A'; // 65저장
char charVal = (char)intVal; // 65에 해당되는 유니코드 문자가 저장된다.
System.out.println(charVal); // 저장된 문자 출력
실수 타입(float, double)은 정수 타입으로 자동 타입 변환되지 않기 때문에 강제 타입 변환을 사용해야 한다.
소수점 이하 부분은 버려지고 (값 손실), 정수 부분만 저장된다.
ex) double doubleVal = 3.14;
int intVal = (int)doubleVal; // intVal는 doubleVal 의 정수 부분인 3만 저장됨
public class CastingExam {
public static void main(String[] args) {
int intVal = 44032;
char charVal = (char)intVal;
System.out.println(charVal); // 44032에 해당되는 유니코드 '가' 출력
long longVal = 500;
intVal = (int)longVal;
System.out.println(intVal); // 500 1byte 이내로 손실없음
double doubleVal = 3.14;
intVal = (int)doubleVal;
System.out.println(intVal); // 정수부분인 3 출력
}
}
강제 타입 변환에서 사용자로 부터 받은 입력값을 변환할 때 값의 손실이 일어나지 않도록 주의해야한다.
따라서 값이 보존할 수 있는지 체크할 필요가 있다.
public class CheckValBeforeCasting {
public static void main(String[] args) {
int i = 128; //변환 대상
if ( (i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE) ) { // (i<-128 || i>127) 과 동일
System.out.println("byte 타입으로 변환 할 수 없습니다.");
System.out.println("값을 다시 확인하세요");
} else {
byte b = (byte) i;
System.out.println(b);
}
}
}
자바에서 데이터 값 검사를 위해 해당 타입의 최대값, 최소값 상수를 제공한다.
기본 타입 |
최대값 상수 |
최소값 상수 |
byte |
Byte.MAX_VALUE |
Byte.MIN_VALUE |
short |
Short.MAX_VALUE |
Short.MIN_VALUE |
int |
Int.MAX_VALUE |
Int.MIN_VALUE |
long |
Long.MAX_VALUE |
Long.MIN_VALUE |
float |
Float.MAX_VALUE |
Float.MIN_VALUE |
double |
Double.MAX_VALUE |
Double.MIN_VALUE |
강제 타입 변환에서 정수 타입을 실수 타입으로 변환할 때 정밀도 손실을 피해야 한다.
public class FromIntToFloat {
public static void main(String[] args) {
int num1 = 123456780;
int num2 = 123456780;
float num3 = num2; //int 변수 num2 를 float로 자동 변환
num2 = (int)num3; //float 변수를 int형으로 강제 변환
int result = num1 - num2;
System.out.println(result); // -4 가 출력된다!?
}
}
위의 예제에서 결과 값이 0이 나와야 의미상 정상이지만 -4가 출력된다.
int 값을 float타입으로 자동 변환 하면서 문제 발생!
float 형의 가수 부분은 23비트 이므로, 123456780은 23비트로 표현할 수 없어서 근사치로 변환된다.
(정밀도 손실 발생)
float 값을 다시 int 타입으로 변환하면 원래의 int 값을 얻지 못한다.
따라서 num1 과 num2는 동일한 값이 아니게 된다.
해결책은 float 대신 double 타입을 사용하면 된다.
3. 연산식에서의 자동 타입 변환과 강제 타입 변환
서로 다른 타입의 피연산자가 있을 경우 두 연산자 중 크기가 큰 타입으로 자동 타입 변환된 후 연산을 수행한다.
int intVal = 10;
double doubleVal = 5.5;
double result = intVal + doubleVal; // result 에 15.5 저장됨
여기서 intVal 는 double 형으로 자동 타입 변환된다.
int 타입으로 연산을 해야 한다면 double 타입을 int 타입으로 강제 변환 후 연산을 수행하면 된다.
int intVal = 10;
double doubleVal = 5.5;
int result = intVal + (int)doubleVal; //result에 15가 저장됨 (소수점 버려짐)
public class OperationPromotionExam {
public static void main(String[] args) {
byte byteVal1 = 10;
byte byteVal2 = 20;
// byte byteVal3 = byteVal1 + byteVal2; 컴파일 에러 연산결과가 int형 이기 때문!
int intVal1 = byteVal1 + byteVal2;
System.out.println(intVal1);
char charVal1 = 'A';
char charVal2 = 1;
// char charVal3 = charVal1 + charVal2; 컴파일 에러 연산결과가 int형 이기 때문!
int intVal2 = charVal1 + charVal2; // 65 + 1
System.out.println("유니코드 = " +intVal2); // 66
System.out.println("출력문자 : "+(char)intVal2); // B
int intVal3 = 10;
int intVal4 = intVal3 / 4; // int형 연산, 소수점 버려짐
System.out.println(intVal4); // 2
int intVal5 = 10;
// int intVal6 = 10 / 4.0; 컴파일 에러 연산결과가 double 이기 때문
double doubleVal = intVal5 / 4.0;
System.out.println(doubleVal); // 2.5
}
}
자바는 정수 연산 시 int 타입을, 실수 연산 시 double 타입을 기본으로 한다.
피연산자를 4byte 단위로 저장하기 때문에,
4byte보다 작은 타입 (byte, char, short)는 int로 변환되어 연산이 수행된다.
연산의 결과도 int형으로 반환된다.
char ai = 'A'; // 유니코드 65
int result = ai + 1; //'A'의 유니코드보다 1이 큰 유니코드 66 저장됨 (덧셈 연산)
char na = (char) result; //'B'가 저장된다.
만약 피연산자중 long 타입이 있다면, 다른 피연산자도 long 타입이 되고, 연산 결과도 long 타입으로 반환된다.
실수 타입 float 와 double도 마찬가지로 적용된다.
피연산자중 double 타입이 있다면,
다른 피연산자도 double 타입이 되고, 연산 결과도 double 타입으로 반환된다.
* 연산 시 자동 타입 변환 정리
- 정수와 실수 연산 = 실수형 타입 (double)
- 정수와 정수 연산 = int 타입
- 실수와 실수 연산 = double 타입
- 큰 타입과 작은 타입 연산 = 큰 타입
'Java 기본 문법 - 참조 서적 [이것이 자바다 - 한빛미디어] > 1. 변수, 기본 데이터 타입, 연산자' 카테고리의 다른 글
6. Java 자바 - 이항 연산자, 삼항 연산자 (0) | 2020.04.24 |
---|---|
5. Java 자바 - 단항 연산자 (0) | 2020.04.24 |
4. Java 자바 - 연산자 종류, 연산자 우선순위 (0) | 2020.04.22 |
2. Java 자바 - 기본 데이터 타입 (0) | 2020.04.20 |
1. Java 자바 - 변수와 리터럴 (1) | 2020.04.20 |