자바에서는 자바스크립트와는 반대 되는 정적 언어입니다. 즉 컴파일 단계에서 이미 데이터의 타입이 정확하게 지정되어 있어야만 오류 없이 런타임에서의 실행이 가능함을 의미하는데요.
그래서 자바에서의 자동 형 변환(타입 캐스팅)은 동적인 타입 캐스팅을 의미하는대에 반해, 자바에서는 주로 각각의 데이터 타입이 올바르게 지정된 후에, 컴파일 과정에서 작은 범위의 데이터 타입에서 큰 범위의 데이터 타입으로 변경 될 때 타입 캐스팅이 주로 일어납니다.
쉽게 말하자면 작은 그릇에 큰 그릇이 들어갈 때 자동 형 변환이 가능하다는 뜻입니다.
byte b = 127; // byte의 최댓값 int i = b; // byte 타입으로 선언된 b의 값은 int 타입의 범위 안에 들어가기 때문에 int형으로 자동 변환됩니다. System.out.println(i); // 출력: 127
반면 타입 캐스팅이 안되는 경우도 있는데, 음수의 범위를 포함하고 있는 정수형 데이터 타입을 문자 타입으로 타입 캐스팅 할 때의 경우로 볼 수 있으며, 대표적인 오류 코드는
Type mismatch: cannot convert from byte to char
입니다.그 이유는 작은 범주의 데이터가 큰 범주의 데이터로 타입 캐스팅 될 때 정상적으로 범주에 포함될 수 없는 데이터이기 때문이죠.
byte b1 = 65; // b1의 데이터 타입은 -128 ~ 127까지의 범위이지만 char ch1 = b1; // ch1의 데이터 타입은 0 ~ 65535까지의 범위, 즉 각각의 데이터의 타입 범위가 일치하지 않으므로 오류 발생.
물론 위의 경우 또한 타입 캐스팅 적용이 가능한데요.
강제 타입 변환
을 사용하면 됩니다. 바꾸고자 하는 데이터 값의 앞에 옮겨갈 데이터 타입을 명시하면 되는 방식 이죠.이러한 방식은 주로 범주에 맞지 않는 데이터 간, 또는 큰 데이터에서 작은 데이터로의 타입 캐스팅을 진행하고자 할 때 주로 사용되는 방식입니다.
종합하자면 자동 형변환이 안되는 타입 캐스팅이 발생될 때 사용자가 직접 명시적으로 변환할 데이터 타입을 지정해 주는 것을 의미하는거죠.
또 쉽게 얘기하면 작은 그릇을 깨트려서 억지로 큰 그릇에 맞춰 넣는 것을 의미합니다.
byte b1 = 65; // 원래라면 범주에서 벗어나지만 char ch1 = (char) b1; // 명시적으로 b1의 데이터를 변환한 뒤 ch1에 할당합니다.
자바는 피연산자들의 타입에 따라 다른 결과값을 제공하며, 동적으로 자동 형변환이 제공되는 자바스크립트와는 달리 피연산자간의 산술 연산에 의한 결과를 담을 변수의 데이터 타입까지도 생각을 해야한다는 주의가 존재하죠.
다음은 각 데이터 간 산술 연산에 따른 타입 캐스팅 과정을 살펴보겠습니다.
- 숫자 데이터 간에 연산
// int형 피연산자의 연산 결과가 정수일 경우 정수형 타입에 할당이 가능합니다. int a = 50; int b = 20; int result = a+b; System.out.println(result); // 70 출력 // 그러나 int형 피연산자의 연산 결과가 실수일 경우 결과값의 소수 부분은 무시되고 정수 부분만 반영됩니다. int a = 50; int b = 20; int result = a/b; // 기대값은 2.5 System.out.println(result); // 그러나 소수점은 버려지고 정수 부분인 2만 출력 // 이를 방지하기 위해서는 피연산자의 한 쪽을 실수형 타입으로 변환한 뒤 연산을 실행해야 올바른 실수 결과값이 나옵니다. float a = 55.0f; // 실수형 피연산자 1 int b = 20; // 정수형 피연산자 2 float c = a/b; // 연산 과정에서 결과값이 나오기 전까지 피연산자 중 한 쪽을 실수로 만들어줘야 최종 연산 때 실수 부분 반영 가능 int d = (int) a/b; // 실수형 결과를 정수형으로 변환하여 소수 부분을 떨군 결과를 담아 출력 가능 System.out.println(c); // 2.75 출력 System.out.println(d); // 2 출력
- 숫자와 문자 간에 계산
// 문자와 숫자 간 연산시 해당 문자를 유니코드(정수)로 치환 후 연산을 수행한 결과값을 정수 및 실수 처리가 가능합니다. char A = "1"; int B = 1; int C = A+B; // A에 할당된 값의 유니코드인 49와 숫자1을 더한 값 50을 C에 할당 System.out.println(C); // 문자열과 숫자 간 연산시 + 기호를 이용한 문자 결합만 가능하며, 그 이외의 연산 기호로 연산시 에러가 발생합니다. String A = "1"; int B = 1; String C = A+B; System.out.println(C);
- 문자 데이터 간에 계산
// 문자형 데이터 간의 산술 연산은 + 기호에 의한 문자 간 결합 연산만 가능. char A = 'A'; String B = "BCDE"; String C = A+B; System.out.println(C); // "ABCDE" 출력
만약 해당 문자열의 값이 온전한 형 변환이 가능한 값으로 이루어져 있을 경우, 각 숫자의 형태에 맞는 타입으로 형 변환 해준 뒤 할당하는 것 또한 가능합니다.
이때는 주로 변화시킬 래퍼 클래스와 parsing 메서드를 활용합니다.
String number1 = "12345"; String number2 = "12.345"; String number3 = "123450000000000"; String number4 = "true"; System.out.println(Integer.parseInt(number1)); // 12345 출력 System.out.println(Float.parseFloat(number2)); // 12.345 출력 System.out.println(Long.parseLong(number3)); // 123450000000000 출력 System.out.println(Boolean.parseBoolean(number4)); // true 출력