산술 변환이란?
이항 연산자는 두 피연산자의 타입이 일치해야 하는데 이 때 자동으로 형변환되는 것을 '산술 변환'이라고 한다.
산술 변환의 규칙에는
1) 작은 타입을 큰 타입으로 변환하여 타입을 일치시킨다
2) int 보다 작은 타입의 경우 int 타입으로 변환한다
가 있다.
산술 변환과 관련해 주의할 케이스
overflow
이항 연산자 중 대입 연산자도 산술 변환이 발생한다
long l = 3 + 5;
3 + 5 는 int + int 이므로 그 결과값도 int 인데 long 타입인 l 에 할당할 때는 long 타입으로 자동 변환이 일어난다.
이 때 주의해야할 점은 우변의 결과값은 기본적으로 int 라는 점이다.
int i1 = 1000000;
int i2 = 2000000;
long l1 = i1 * i2;
long l2 = (long)i1 * i2;
System.out.println(l1); // i1 * i2 는 int 의 범위를 넘어가 overflow 가 발생하고 그 결과가 l1 에 저장
System.out.println(l2);
i1 * i2 의 결과값은 int 가 표현할 수 있는 범위를 넘어선다. 따라서 int * int 형태인 첫 번째 식은 overflow 가 발생한 결과값이 l1 에 저장이 된다.
반면 두 번째 식은 i1 을 long 으로 형변환 한 것으로 인해 i2 도 자동으로 long 으로 형변환이 되어 long * long 의 결과가 l2 에 저장이 되므로 overflow가 발생하지 않고 의도한 결과값이 저장이 된다.
int 보다 작은 타입의 자동 변환
int 보다 작은 타입은 산술 연산의 피연산자가 될 경우 자동으로 int 로 변환이 된다. 따라서 타입에 유의해야 한다.
byte b1 = 10;
byte b2 = 30;
byte b3 = b1 + b2;
산술 변환이 일어나지 않는다고 생각하면 byte + byte 의 결과가 byte 에 할당되는 것이므로 아무 문제가 없지만 실제로는 산술 변환에 의해서 int + int 의 결과가 byte 에 할당되는 것이라서 타입 불일치로 인해 컴파일 에러가 발생한다.
char 타입도 마찬가지다.
char c = 'a';
char c1 = c + 1;
char 타입은 int 보다 작기 때문에 c + 1 에서 int 타입으로 변환이 되어 우변의 결과는 97 + 1 = 98 이 된다.
96 이라는 int 타입의 값을 char 타입에 할당하려고 하니 컴파일 에러가 발생한다.
다만 리터럴과 상수 간의 연산은 런타임시 변경될 우려가 없어서 컴파일러에서 먼저 연산을 수행하여 컴파일 코드를 작성하게 되어 에러가 발생하지 않는다.
char c1 = 'a' + 1;
System.out.println(c1); // b
그렇다면 ++ 연산이나 -- 연산을 수행하면 어떻게 될까?
char c = 'A';
System.out.println(++c);
System.out.println(--c);
System.out.println(c + 1);
++ 연산은 c + 1 이랑 똑같고, -- 연산은 c - 1 이랑 같으니 산술 변환이 발생할까? 그렇지 않다. 값이 하나 더해지거나 빼지는 것은 맞지만 ++, -- 연산은 int 타입과 연산을 수행한 것이 아니라 본연의 값 자체에 연산을 수행한 것이기 때문에 char 타입이 그대로 유지된다.
'Java' 카테고리의 다른 글
문자열(String)의 생성과 비교 (0) | 2023.10.08 |
---|---|
비트 연산자(<<, >>, &, |, ^, ~) (0) | 2023.09.19 |
스레드 동기화(synchronized) (0) | 2023.04.12 |
상속 (0) | 2023.04.07 |
접근제어자와 Getter & Setter (0) | 2023.04.06 |