형 변환(casting)
코딩을 하다보면 여러 데이터를 만나게 되고 그 처리과정에서
같은 타입의 데이터로 맞춰주어야 할 필요성을 느끼는 경우가 많다.
가령 문자열로 입력받은 데이터 "1234" 와 숫자로 입력받은 데이터 3의 연산을 위해서 등
현재 데이터의 자료형은 다르지만 연산을 하기위해서라든가,
혹은 같은 자료형으로 취급해서 처리하기 위함등 여러 경우에서 서로 다른 형태의 자료형을
같은 자료형으로 바꾸는 경우가 생긴다.
이런 것을 바로 형변환 즉 캐스팅이라 부르는데
이런 형변환 방법은 크게 두가지로 나뉜다.
1. 묵시적 형변환
자바에서는 데이터의 손실을 최소한으로 하는 방향으로 형변환이 이루어지는데
자료형에 따라 메모리 공간을 더 적게 소모하는 자료형에서
더 많이 소모하는 자료형으로의 형변환은 별도의 형변환의 명시가 없어도 자동으로 이루어진다.
즉, 작은 그릇에 담긴것을 큰그릇으로 옮기는것은 데이터의 손실이 일어나지 않기 때문에 별도의 방법을 요구하지 않는다.
이런 자료형의 메모리 사용량은 이전에 작성한 단순자료형의 표를 참고하면 된다.
https://0bliviat3.tistory.com/35
단순자료형
이번 포스팅에서는 자바에서 사용하는 단순 자료형에 대해 다뤄보겠다. 기본적으로 자바는 객체지향언어로서 우리가 사용하는 혹은 생각하는 모든 것들을 객체로서 표현하는것을 지향한다. 이
0bliviat3.tistory.com
조금 보기 쉽게 그림으로 표현 하면 다음과 같다.
이런 묵시적 형변환의 과정을 코드로 보면 다음과 같다.
short a = 1;
int b = 2;
int c = a + b;
System.out.println(c);
단순히 별도의 명시가 없어도 short 타입인 a가 더 큰 메모리 공간을 할당하는 int 타입 b를 만나 int로 묵시적 형변환되어
연산이 됨을 볼 수 있다.
조금 특이한 점은 이제 다음 같은 출력일때 느낄수 있는데
일단 먼저 코드를 보겠다.
char a = '1';
int b = 2;
int c = a + b;
System.out.println(a);
System.out.println(c);
그리고 출력된 값은 다음과 같다.
이건 문자 타입인 a 와 int 타입인 b가 만나 연산시 a가 int 타입으로 묵시적 형변환 되어 연산되는데
이때 문자타입은 해당 문자의 아스키코드값으로 변환되어 연산하게 되는것이다.
https://ko.wikipedia.org/wiki/ASCII
ASCII - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 1972 프린터 사용 설명서에 개시된 아스키 코드 차트표 미국정보교환표준부호(영어: American Standard Code for Information Interchange), 또는 줄여서 ASCII( , 아스키)는 영문
ko.wikipedia.org
위의 링크에 있는 아스키코드표에서 '1'에 해당하는 문자의 십진수를 보면 49인데
이 값이 b에 저장되어있는 2와 연산된 결과 51로 출력되는것이다.
2. 명시적 형변환 (강제적 형변환)
명시적 형변환은 자료형이 갖는 메모리의 할당 공간이 더 작은 메모리의 할당 공간을 갖는 자료형으로 형변환시 사용된다.
이 경우엔 형변환 문법인
(바꾸려는 자료형) 변수명
꼴의 캐스팅 연산자를 통해 형변환이 가능하다.
주의해야 할 점은 큰 그릇의 담긴 데이터를 작은 그릇으로 옮기려는 작업과 동일하므로
데이터의 손실이 발생할수 있다는 점이다.
가령 실수 타입인 double 로 선언된 변수 a가 정수타입인 int로 강제적 형변환을 하는 경우
소수점 자리 이하 데이터는 버림 취급한다.
코드로 한번 이 과정을 보면 다음과 같다.
double a = 1.123;
int b = (int) a;
System.out.println(b);
또 다른 경우를 예를 들어보겠다.
long 타입의 변수 a가 int 타입으로 형변환하는 경우 또한 데이터의 손실을 생각해야하는데
int의 범위를 벗어나는 데이터를 형변환 하는 경우 오버플로우가 발생해 아예 예상못한 데이터를 갖게된다는 점이다.
역시 코드로 한번 보도록 하겠다.
long a = Long.MAX_VALUE;
int b = (int) a;
System.out.println(a);
System.out.println(b);
다음과 같은 코드를 실행시켜보면
원하는 데이터는 long 타입의 최대 상수를 가져와야하지만 오버플로우가 발생해 -1을 갖는것을 볼 수 있다.
이처럼 형변환은 가능하나 데이터손실을 생각해서 예상못한 결과가 나오는것을 고려해 코딩해야 한다.
또 이런 묵시적 형변환, 명시적 형변환은 원시타입의 자료형에만 국한되는것이 아닌 참조타입의 자료형도 마찬가지로
적용이 되는데 같은 맥락에서 하위의 클래스에서 상위의 클래스로 형변환시엔 묵시적으로,
상위의 클래스에서 하위의 클래스로 형변환시엔 명시적 형변환을 사용하면 된다.
String[] arr = new String[3];
Object[] arr1 = arr;
String[] arr2 = (String[]) arr1;
모든 객체의 최상위 클래스인 Object로 형변환시엔 묵시적인 형변환이 가능하지만,
그 반대의 경우 명시적 형변환을 해주어야 한다.