JAVA 형변환
변수의 데이터 타입을 변환하는 처리를 형변환 혹은 타입변환이라고 합니다. 주로 정수와 실수간의 상호 변환 과정에서 이루어지며 다른 타입간에도 가능합니다.
#01. 암묵적 형변환
1) 정수의 경우
리터럴의 형변환
소스코드에 단독으로 명시되는 숫자나 문자열, 논리값 등을 리터럴이라고 한다.
정수 형태의 리터럴은 기본적으로 int 타입으로 식별된다. byte, short, long 타입의 변수에 리터럴을 대입하는 코드는 컴파일시에 int 타입에서 암묵적으로 형변환 된다.
아래의 코드는 모두 int 형의 리터럴을 다른 정수 타입으로 형변환 처리 한다.
1
2
3
4
// int 타입의 리터럴을 다른 타입으로 변환하는 것으로 간주
byte a = 1;
short b = 2;
long c = 3;
이미 선언된 변수를 다른 타입에 대입하는 경우
최초로 선언된 변수보다 더 큰 크기의 메모리를 차지하는 데이터 타입의 변수에는 특별한 처리 없이 대입이 가능하다.
예를 들어 int형의 변수를 long 타입의 변수에 대입하는 것은 4byte의 공간에 저장된 데이터를 8byte의 공간으로 옮기는 것이므로 아무런 문제가 없다.
1
2
int a = 10; // 4byte
long b = a; // 8byte
반대로 8byte의 메모리를 차지하는 long 타입의 변수를 4byte 공간의 int 형 변수에 대입하는 경우 메모리 공간의 부족으로 인한 데이터 손실이 발생하므로 컴파일시에 에러가 발생한다.
1
2
long a = 10; // 8byte
int b = a; // 4byte <-- 에러
위의 코드는 아래와 같이 long에서 int로 변환할 수 없다(from long to int)는 내용의 에러가 발생한다.
1
2
3
4
Test.java:4: error: incompatible types: possible lossy conversion **from long to int**
int b = a;
^
1 error
2) 실수의 경우
리터럴의 형변환
실수 형태의 리터럴 값은 기본적으로 double로 인식된다. 그렇기 때문에 float 타입의 변수에 실수를 대입하는 것은 8byte의 메모리 공간의 데이터를 4byte 공간으로 옮기는 것으로 간주되어 에러가 발생한다.
1
float a = 3.14;
아래와 같이 double 타입을 float 타입에 대입할 수 없다는 내용의 에러가 발생한다.
1
2
3
4
Test.java:3: error: incompatible types: possible lossy conversion **from double to float**
float a = 3.14;
^
1 error
float 타입으로 선언된 변수에 리터럴을 대입하기 위해서는 Float 형임을 알려주기 위해 리터럴 뒤에 F
를 붙여야 한다. (대소문자 가리지 않음)
1
2
float a = 3.14F;
float b = 12.345f;
이미 선언된 변수를 다른 타입에 대입하는 경우
float 타입의 변수를 double형에 대입하는 것은 성립되지만 반대의 경우는 성립되지 않는다.
1
2
float a = 10.5F; // 4byte
double b = a; // 8byte의 공간에 대한 대입이므로 성립함.
1
2
double a = 10.5; // 8byte
float b = a; // 4byte <-- 에러
3) char 타입의 경우
char
타입은 홑따옴표로 감싼 한 글자를 의미.
리터럴의 형변환
모든 숫자형 변수에 직접 대입 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
byte num1 = 'a';
short num2 = 'a';
int num3 = 'a';
long num4 = 'a';
float num5 = 'a';
double num6 = 'a';
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
System.out.println(num4);
System.out.println(num5);
System.out.println(num6);
출력결과
1 2 3 4 5 6
97 97 97 97 97.0 97.0
아스키 코드
컴퓨터에서 사용되는 모든 글자에 적용된 일련번호
알파벳 a의 아스키 코드는 97이다.
char
타입의 리터럴을 숫자형 변수에 대입할 경우 자동으로 아스키 코드로 변환되어 진다.
97을 이진수로 변환하면 1100001인데 이는 알파벳 a의 바이너리 데이터인 01100001와 일치한다.
즉, 아스키 코드는 글자를 바이너리로 변환한 상태를 10진수로 표현한 값.
char 타입의 알파벳 a
와 b
를 더한 결과를 int
타입의 변수에 할당하면, a
의 아스키코드 97과 b
의 아스키 코드 98에 대한 합산 결과가 표시된다.
1
2
int k = 'a' + 'b';
System.out.println(k);
출력결과
1
195
이미 선언된 변수를 다른 타입에 대입하는 경우
자바에서는 char 타입에게 2byte의 메모리 공간을 할당한다. 그러므로 1byte의 크기를 갖는 byte 타입과 같은 크기의 공간을 차지하는 short 타입을 제외한 모든 형태의 숫자형 변수에 대입 가능하다.
1
2
char word = 'a';
byte num1 = word; // <-- 에러
1
2
char word = 'a';
short num2 = word; // <-- 에러
그 외의 경우는 문제 없음
1
2
3
4
5
char word = 'a';
int num3 = word;
long num4 = word;
float num5 = word;
double num6 = word;
4) 그 밖의 경우
- 모든 형태의 정수형 변수는 모든 형태의 실수형 변수에 대입 가능하다.
long
타입의 정수형 변수는float
타입보다 메모리 크기가 더 크지만long
에서float
로의 암묵적 형변환은 허용된다.
- 모든 형태의 실수형 변수는 모든 형태의 정수형 변수에 대입 불가능하다.
float
타입의 실수형 변수는long
타입보다 메모리 크기가 더 작지만float
에서long
으로의 암묵적 형변환은 허용되지 않는다. (소수점 이하 자리에 대한 오차가 불가피하기 때문.)
boolean
타입은 어떠한 타입으로 변환 불가능.
5) 암묵적 형변환에 대한 결론
- 정수는 실수로 변환 가능. 실수는 정수로 변환 불가능.
- 정수끼리 혹은 실수끼리는 메모리 크기가 더 큰 타입으로는 변환 가능. 반대는 불가능.
char
타입의 경우int
형 이상의 메모리 크기에는 대입가능.- 이론적으로는 메모리 크기에 대한 데이터 이동 제약이지만 자바에서는 단순히 값에 대한 표현 범위로 이해하는 것이 더 효율적이다.
📗 Ex01_자동형변환.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Ex01_자동형변환 {
public static void main(String[] args) {
/** 1) 자동 형변환 */
// 작은 크기의 메모리에서 큰 크기로 변환
int number = 10; // int 자료형
long number2 = number; // 자동형변환 int < long
System.out.println(number2);
/** 2) 자동 형변환의 예외 상황 */
// 정수 --> 실수 변환시에는 메모리의 크기보다 값의 표현을 더 중요시 함.
// float로의 변환은 권장하지는 않음.
// double을 사용할 것
float number3 = number2;
System.out.println(number3);
}
}
📗 Ex02_CharType.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Ex02_CharType {
public static void main(String[] args) {
/** 1) char 타입은 한 글자를 저장할 수 있다. */
// char 타입의 값을 할당할 때는 홑따옴표로 글자를 감싼다.
char a = 'A';
System.out.println(a);
/** 2) char 타입을 정수형으로 변환 */
// 'A'에 해당하는 아스키코드로 자동 변환된다.
int b = a;
System.out.println(b);
/** 3) 66을 char타입으로 변환 */
// 아스키코드 66이 의미하는 글자로 자동 변환된다.
char c = 66;
System.out.println(c);
/** 4) char 타입의 변수는 정수로 인식되기 때문에 연산이 가능 */
int B = 'A' + 1;
int C = 'A' + 2;
int D = 'A' + 3;
// char B = 'A' + 1;
// char C = 'A' + 2;
// char D = 'A' + 3;
System.out.printf("B=%s, C=%s, D=%s", B, C, D);
}
}
#02. 명시적 형변환
암묵적 형변환에서 에러가 발생하는 경우는 메모리 크기의 차이로 인한 데이터의 손실이 발생하는 경우이다.
데이터의 손실을 감수하고서라도 강제로 타입을 변환하는 처리를 명시적 형변환이라고 한다.
적용방법
할당하는 리터럴이나 변수앞에 변환할 타입을 직접 명시한다.
실수형 값을 정수형으로 강제 변환 할 경우 소수점 아래자리는 모두 버려진다.
1
2
double k = 12.345;
int a = (int) k;
📗 Ex03_강제형변환.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Ex03_강제형변환 {
public static void main(String[] args) {
// double 자료형에 정수를 대입하면 자동 형변환이 발생하여 100.0이 된다.
double score = 100;
System.out.println(score);
// 강제로 형변환을 처리할 경우 대입할 변수 앞에 변환하고자 하는 타입을 명시
int score2 = (int) score;
System.out.println(score2);
double pi = 3.141592D;
System.out.println(pi);
// 실수 타입을 정수로 변환할 경우 소수점 이하는 모두 버린다.
// --> 데이터의 손실을 감수함
int pint = (int) pi;
System.out.println(pint);
}
}
📗 Ex04_연산결과_형변환.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Ex04_연산결과_형변환 {
public static void main(String[] args) {
/** 1) 기본적으로 연산 결과는 피연산자의 데이터타입을 따름 */
// ex) 정수끼리의 연산 결과는 정수
int x = 100;
int y = 50;
System.out.println(x+y);
/** 2) 서로 다른 타입의 연산 결과는 더 큰 범위의 데이터 타입으로 결과가 생성 */
double m = 123.45;
int n = 67;
System.out.println(m + n);
/** 3) 연산 결과에 대해 자동 형변환 가능 */
int i = 10;
int j = 20;
double k = i + j;
System.out.println(k);
/** 4) 연산 결과에 대해 강제 형변환 가능 */
// (10.2 + 3.1)이 괄호로 묶였기 때문에 (10.2 + 3.1)의 결과에 대해 형변환
//int a = 10.2 + 3.1;
int a = (int)(10.2 + 3.1);
System.out.println(a);
// 아래 코드는 (int)가 10.2에만 영향을 줌
// 10 + 3.1이 되어 결과가 13.1이 되기 때문에 정수에 대입할 수 없음.
// int b = (int)10.2 + 3.1;
}
}
형변환 연습문제
신체질량지수(BMI: Body Mass Index)에 의한 비만도
비만의 판정의 올바른 지표는 체중이 아니라 체지방량이므로 몸의 지방량을 직접 측정하는 것이 이상적이나 이것은 기술적인 어려움이 있기 때문에 표준체중이나 신체질량지수 등 체지방량을 간접적으로 측정하는 방법이 일반적 입니다.
계산식
1
신체질량지수(BMI) = 체중(kg) / (신장(m))^2
(체중) 나누기 (신장의 제곱)
판정기준
판정 | 범위 |
---|---|
저체중 | 20미만 |
정상 | 20 - 24 |
과체중 | 25 - 29 |
비만 | 30 이상 |
프로그램 요구사항
- 사용자로부터 체중을 의미하는 정수형 변수
myWeight
와 키를 의미하는 실수형 변수myHeight
를 입력 받습니다. - 체중 변수는 kg 단위로 입력 받고, 키 변수는 m 단위로 입력 받습니다.
- 입력 받는 과정에서 표시되는 메시지는 개발자가 임의로 정의할 수 있습니다.
- BMI 산출 식을 적용하여 BMI 수치를 정수 형태로 출력합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Scanner;
public class 연습문제 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("체중을 입력하세요(kg): ");
int myWeight = reader.nextInt();
System.out.print("키를 입력하세요(m): ");
double myHeight = reader.nextDouble();
reader.close();
// 1) double로 계산 후 출력시 정수로 변환
double bmi = myWeight / (myHeight * myHeight);
System.out.println((int) bmi);
// 2) 계산 결과를 정수로 변환
int bmi2 = (int) (myWeight / (myHeight * myHeight));
System.out.println(bmi2);
}
}