안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
형변환에 대해 알아보기에 앞서 프로그래밍에 작동 원리가 있습니다.
① 값(Literal)은 같은 자료형의 변수에만 대입 할 수 있다.
② 같은 자료형 사이에서 연산이 가능하다. (ex. 3 + 3 → 가능 // 3 + 3.0 → 원칙적으론 불가능)
③ 같은 자료형 간 연산 결과는 동일한 자료형이다. (ex. 3 + 5 = 정수형 // 5 /2 = 정수형)
하지만 때로는 다른 자료형 즉, 정수 + 실수 혹은 정수 / 실수 등 작동 원리를 벗어나는 연산을 할 수도 있을 뿐 더러,
반드시 동일한 자료형의 연산 결과만을 얻지 않고 싶을 때도 있을 것 입니다. (ex. 5 나누기 2 = 2.5 결과를 원함)
이러한 문제점을 해결하기 위해서 하는 것이 형변환 (Casting) 입니다.
형변환에는 2가지 종류가 있는데요,
① 암묵적(자동) 형변환 - JVM이 처리
② 명시적(강제) 형변환 - (자료형)으로 표현
먼저 암묵적(자동) 형변환에 대해서 알아 보겠습니다.
이전 자료형에 대해 배우면서 각 자료형 간의 크기가 정해져있다는 것을 알 수 있었습니다.
형변환을 하고자하는 각 자료형들의 크기에 따라 암묵적이냐 명시적이냐가 나뉩니다.
암묵적(수동) 형변환
여기서 암묵적 형변환이란?
크기가 작은 타입에서 큰 타입으로 변환하고자 할 때 사용됩니다. (데이터 손실 X)
순서는 아래와 같습니다.
byte (1byte) → short/char (2byte) → int (4byte) → long (8byte) → float (4byte) → double (8byte)
* boolean은 형변환의 개념이 없습니다.
여기서 2가지의 의문점이 생길 수 있습니다.
① char는 문자형인데 왜 int인 정수형으로 암묵적 형변환이 가능할까?
☞ char → int로 변환 시에는 ASCII CODE 에 의해 변환됩니다.
컴퓨터는 숫자만을 인식할 수 있기 때문에 모든 문자는 숫자로 변환되어 관리가 됩니다.
(ASCII code table https://www.ascii-code.com/ )
② long은 8byte고 float은 4byte인데 왜 암묵적 형변환이 가능할까?
☞ float/double은 지수표현식으로 표현되는데, 지수표현식은 더 많은 수를 표현할 수 있습니다.
즉, int/long에 비해 크기는 작지만 표현할 수 있는 수의 범위가 더 넓기 때문에 암묵적 형변환이 가능합니다.
그럼 코드로 확인해보겠습니다.
public void test() {
byte bnum = 100;
int inum = bnum; // int = byte -> int = (int)byte -> int = int
System.out.println(inum);
}
@콘솔출력값
100
* 형변환은 자료형 앞에 (자료형)을 붙여서 표현합니다. (암묵적 형변환은 JVM이 자동으로 처리)
* int inum = bnum; 은 작동 원리 2번 사항을 위배하였습니다.
다만, byte가 int로 암묵적 형변환 처리가 되며 결론적으론 int = int의 연산이 수행되어 원하는 결과 값을 리턴할 수 있었습니다.
public void test() {
int i = 10;
double d = 5.8;
System.out.println(i + d); // int + double -> (double)int + double -> double + double
char ch = 'C';
int inum = ch; // int = char -> int = (int)char -> int = int
System.out.println(inum);
System.out.println('A' + 100); // char + int -> (int)char + int -> int + int
}
@콘솔출력값
15.8
67
165
* int + double 과 char = int 의 결과 값도 위와 같이 암묵적 형변환을 통하여 위와 같은 결과 값을 리턴하였습니다.
* inum은 'C'의 ASCII CODE 값인 67을, 'A'의 ASCII CODE 값인 65을 리턴한 것을 확인할 수 있었습니다.
명시적(강제) 형변환
명시적(강제) 형변환이란?
크기가 큰 타입에서 작은 타입으로 변환하고자 할 때 사용됩니다. (데이터 손실 O)
순서는 암묵적 형변환의 반대입니다.
byte (1byte) ← short/char (2byte) ← int (4byte) ← long (8byte) ← float (4byte) ← double (8byte)
명시적 형변환의 경우, 데이터 손실이 발생할 수 있기 때문에 JVM이 자동 형변환 처리를 해주지 않습니다.
따라서 개발자 측에서 직접 명시적으로 타입 변환을 해주어야 합니다.
그럼 코드로 확인해보겠습니다.
public void test() {
//데이터 손실 감수하고 소수점 이하 버림
double dnum = 34.567;
System.out.println(dnum);
System.out.println("소수점 필요 없음 - " + (int)dnum); //(int)double -> int로 명시적 형변환
// 소수점 표시를 원함
System.out.println(5 / 2); // int/int = int
System.out.println((double)5 / 2); // int/int -> (double)int/int -> double/(double)int
int i = 5;
int j = 2;
System.out.println((double)i / j);
// double(int)/int -> double/int -> double/(double)int -> double/double
// overflow 방지 (실제로 MAX_VALUE 값에 1을 더한 값을 출력하고 싶음)
int inum = Integer.MAX_VALUE;
System.out.println(inum);
System.out.println(inum + 1); // overflow 발생
System.out.println((long)inum + 1);
// (long)int + int -> long + int -> long + (long)int -> long -> long
System.out.println(inum + 1L); // 이렇게도 표현 가능
}
@콘솔출력값
34.567
소수점 필요 없음 - 34
2
2.5
2.5
2147483647
-2147483648
2147483648
2147483648
명시적 형변환의 목적
① 데이터 손실을 감수하고 소수점 이하를 버릴 때
☞ dnum 처럼 34.567의 실수를 정수로 바꾸고 싶을 때 (int)dnum 으로 명시적 형변환을 통해 원하는 값을 리턴할 수 있습니다.
② 소수점 표시를 원할 때
☞ 5 / 2 (i / j) 를 하게 되면 int 나누기 int 이므로 결과는 항상 int값이 나오게 됩니다. (2)
하지만 2.5를 출력하고 싶을 때 즉, int가 아닌 double 값으로 리턴하고 싶을 대 (double)5 /2 ((double)i/j) 으로 명시적 형변환을 통해 원하는 값을 리턴할 수 있습니다.
③ Overflow를 방지하고 싶을 때
☞ Integer.MAX_VALUE + 1을 하게 되면 최소값인 -2147483648 값을 출력하게 됩니다. (overflow 로 인하여)
다만, 실제로 최대값에 +1 (2147483648)을 한 결과를 리턴하고 싶을 때 명시적 형변환을 통해 원하는 값을 리턴할 수 있습니다.
(int에서는 (long)inum으로 변환시켜줌)
예외상황
① int 보다 작은 자료형 (byte, short, char)은 연산 시 int로 변환되어 처리
② int → char로도 암묵적 형변환 처리 가능
예외상황들도 코드로 확인해보았습니다.
public void test() {
byte a = 3;
byte b = 5;
// byte ab = a + b; // 오류 = byte + byte -> int + int로 처리
byte ab = (byte)(a + b);
System.out.println(ab); //8
System.out.println('b' + 'B'); // 164 : char + char -> int + int로 처리
char ch = 97; // char = int -> char = (char)int로 암묵적 형변환
System.out.println(ch); // a
}
@콘솔출력값
8
164
a
* 변수 ab의 경우, byte + byte를 byte 자료형 변수에 담으려고 하였는데 오류가 났습니다.
프로그래밍 작동 원리에 결코 벗어나는 연산이 아닌데 그 이유는 무엇일까요?
☞ 예외 상황 1번 (byte, short, char는 연산 시 반드시 int로 변환되어 처리) 때문입니다.
CPU에서의 연산 최소 단위가 int이기 때문에 int보다 작은 자료형도 일단 int로 읽어와서 수행하기 때문에 반드시 short + short 혹은 byte + byte 혹은 byte + short 등의 연산 결과를 byte / short / char로 담고 싶다면 명시적 형변환을 해주어야 합니다.
* b + B도 char + char 이지만 int + int로 처리하여 유니코드 b와 B를 더한 164가 출력 되었습니다.
* ch 에 97 즉 char = int 이지만 예외상황 2번에 따라 (char)int로 암묵적 형변환 처리 되어 ch는 a가 출력 되었습니다.
☞ 문자를 저장할 때는 유니코드 표를 보고 문자에 해당하는 정수로 바꿔 메모리에 저장한다고 하였습니다.
char 자료형 메모리 안은 문자가 아닌 정수로 저장된 형태 이기 때문에 반대로 char에 문자에 해당되는 정수값을 입력하여도 동일한 결과를 얻을 수 있게 됩니다.
(char자료형에 정수를 저장할 수 있는 이유!!)
위 내용들을 참고하여 캐스팅 과정 및 리턴 값들을 예측해보았습니다^^
public void test() {
System.out.println('A' + 0); // char + int -> (int)char + int -> 65
System.out.println('0' + 0); // char + int -> (int)char + int -> 48
byte bnum = 125;
char ch = 'C'; //67
int inum = bnum - ch; //int = byte-char -> int = int - int ->
System.out.println(inum); //58
// == 동등비교 연산자 : 좌항, 우항의 값이 동일한 경우 true
// != 부정비교 연산자 : 좌항, 우항의 값이 다른 경우 true, 같으면 false
boolean bool = (2.0 == 2); // double == int -> double == (double)int -> double(2.0) == double(2.0)
System.out.println(bool); //true
bool = (2.0 != 2); // double == int -> double == (double)int -> double(2.0) == double(2.0)
System.out.println(bool); //false
bool = (2.0 == (5 / 2)); // double == int -> double == (double)int -> double(2.0) == double(2.0)
System.out.println(bool); //true
bool = ('A' == 'B' - 1); // int(65) == int(66-1) -> 65 == 65
System.out.println(bool); // true
bool = ('a' != 97); // char != int -> (int)char != int -> int(97) != int(97)
System.out.println(bool); //false
}
@콘솔출력값
true
false
true
true
false
Do it! 자바 완전 정복을 참고하여 포스팅하였습니다.
'Java > Java' 카테고리의 다른 글
Scanner 클래스란?, next()메소드, nextLine()메소드 (0) | 2022.03.01 |
---|---|
문자열을 저장하는 String 참조형이란?, String 특징, String + 연산 (0) | 2022.02.28 |
데이터 오버플로우 (Data Overflow)란? (0) | 2022.02.25 |
상수 (Constant Variable)란? (0) | 2022.02.25 |
변수와 자료형의 종류, 기본 자료형이란? (0) | 2022.02.25 |