자바의 정석 책을 공부하고 정리한 글입니다!
혹시라도 틀린 부분이 있다면 친절하게 알려주세요.
감사합니다!
CH3. 연산자
연산자란 '연산을 수행하는 기호'를 말합니다. 연산자가 연산을 수행하려면 연산의 대상이 있어야 하는데, 이 대상을 피연산자라고 합니다. 다음과 같이 'x + 3'이라는 식이 있을 대, '+'는 연산자, x와 3은 피연산자가 됩니다.
대부분의 연산자는 덧셈 연산자(+)와 같이 두 개의 피연산자를 필요로 하며, 하나 또는 세 개의 피연자를 필요로 하는 연산자도 있습니다. 이러한 연산자는 피연산자로 연산을 수행하고 나면 항상 결과값을 반환합니다.
연산자의 종류는 다음 표와 같습니다:
피연산자의 개수에 따라 단항 연산자, 이항 연산자, 삼항 연산자라고도 분류할 수도 있습니다.
연산자의 우선순위와 결합규칙
수학에서는 덧셈, 뺄셈보다 곱셈, 나눗셈의 우선순의가 높다는 규칙이 있습니다. 이처럼 프로그래밍의 연산자에서도 우선순위가 정해져 있으며, 우선순위가 높은 것을 먼저 계산한 후, 낮은 것들을 처리하죠.
만약 하나의 식에 같은 우선순위의 연산자들이 여러 개 있는 경우, 어떤 순서로 연산을 수행할까요? 우선순위가 같다고 해서 아무거나 먼저 처리하는 것이 아니라 나름대로의 규칙이 있는데 이를 연산자의 결합규칙이라고 합니다.
다음의 식처럼 연산자의 결합규칙은 연산자마다 다르답니다!
3 + 4 - 5의 경우, 덧셈연산자를 수행한 후, 뺄셈연산자를 수행합니다. 즉, 왼쪽에서 오른쪽으로 계산을 하지요! 반면, x = y = 3 의 경우 'y=3' 이 먼저 수행된 후, y에 저장된 값을 x에 대입합니다. 따라서 결합규칙이 오른쪽에서 왼쪽으로 연산을 수행합니다.
연산자의 우선순위를 정리하면 다음과 같습니다:
- 연산자의 우선순위: 산술 > 비교 > 논리 > 대입
- 연산자의 우선순위: 단항 > 이항 > 삼항
- 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽이다.
산술 변환
이항 연산자는 두 연산자의 타입이 일치해야 연산이 가능하므로, 피연산자 타입이 서로 다르다면 연산 전 형변환 연산자로 타입을 일치시켜야 합니다. 저번 글에서 정리한 것처럼 두 피연산자의 타입을 일치시킬 때는 더 큰 타입으로 일치시켜야 하는데, 작은 타입에서 큰 타입으로 형변환하는 경우 형변환 연산자는 생략이 가능합니다! (= 자동형변환)
이처럼 연산 전에 피연산자 타입의 일치를 위해 자동형변환되는 것을 산술 변환 또는 일반 산술 변환이라 합니다.
산술 변환의 규칙은 다음과 같습니다:
- 두 피연산자의 타입을 같게 일치시킨다. (작은 타입으로 변환하면 오버플로우 발생 가능성이 높아, 보다 큰 타입으로 일치)
- 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.
증감 연산자
증감 연산자는 단항 연산자로 증가 연산자(++),감소 연산자(--) 가 있습니다.
- 증가 연산자(++): 피연산자의 값을 1 증가시킨다.
- 감소 연산자(--): 피연산자의 값을 1 감소시킨다.
증감 연산자는 피연산자의 왼쪽에 있는지(전위형), 오른쪽에 있는지(후위형)에 따라서도 결과값이 달라집니다.
- 전위형: 값이 참조되기 전에 증가시킨다. ex) ++i
- 후위형: 값이 참조된 후에 증가시킨다. ex) i++
int i = 1;
System.out.println(++i); // 함수가 실행하기 전 미리 1 증가 (i=2), 2 출력
System.out.println(i++); // 2를 출력한 후, 1 증가 (즉, 함수가 실행된 후, 증가, i=3)
System.out.println(i); // 증감연산자가 없으므로 현재의 i값인 3 출력
저는 처음 증감 연산자를 배울 때, 이해하기 힘들었지만 직접 사용하고 예제로 만들어보시면 빠르게 이해하실 수 있을 겁니다!
산술 연산자
산술 연산자는 예시를 보며 설명하겠습니다.
1.
int x = 10;
int y = 4;
System.out.println(x / y); // 2 출력: 소수점 아래는 버려짐
System.out.println((float)(x / y)); // 2.0 출력: 연산을 진행 후 형변환한 것이라 2 -> 2.0으로 변환
System.out.println((float)x / y); // 2.5
System.out.println(x / (float)y); // 2.5
나누기 연산자를 수행 중 두 피연산자 모두 int 형이면 연산결과 역시 int형입니다.
따라서 2.5를 출력하고 싶다면, 5, 6라인같이 x 혹은 y를 float형으로 변환하시면 됩니다!
2.
byte a = 10;
byte b = 20;
byte c = a + b; // 오류 발생
a와 b는 모두 int형보다 작은 byte형이기 때문에 덧셈 연산자는 이 두 개의 피연산자를 int형으로 형변환 후, 연산을 진행합니다. 따라서 a+b의 결과는 int형이 되는데, int형(4byte)을 byte(1byte)의 변수에 형변환 없이 저장하려고 했기 때문에 오류가 발생하는 것입니다! 오류가 발생하지 않을라면 byte c = (byte) (a + b) 와 같이 형변환을 해주셔야 합니다.
3.
char c1 = 'a'; // c1에는 'a'의 코드값(97) 저장
char c2 = c1; // c1에 저장되어 있는 값 저장
char c3 = ' '; // 공백으로 초기화
int i = c1 + 1; // 'a' + 1 -> 97 + 1
// c3 = c1 + 1; 오류 발생
c3 = (char) (c1 + 1); // (char)(97 + 1)
char c4 = 'a' + 1;
c2++;
c2++;
System.out.println(i); // 98 출력
System.out.println(c2); // c 출력
System.out.println(c3); // b 출력
System.out.println(c4); // b 출력
주석으로 오류 발생이라 적힌 부분에서 왜 오류가 나는지 설명해드리겠습니다.
우선, c1 + 1의 연산결과는 int형이며, 그 결과를 char형으로 형변환하지 않았기 때문에 오류가 발생합니다. 그런데 덧셈 연산자와 같은 이항 연산자는 int보다 작은 타입의 피연산자를 int로 자동 형변환한다고 배웠는데, 왜 오류가 나는 것일까요? 그리고 char c4 = 'a' + 1;은 왜 문제가 없을까요?
그 이유는 'a' + 1가 리터럴 간의 연산이기 때문입니다! 리터럴 또는 상수의 경우에는 실행과정동안 값이 변하지 않기 때문에, 컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로써 코드를 보다 효율적으로 만듭니다.
그러나 c3 = c1 + 1의 경우, 수식에 변수가 있어 컴파일러가 미리 계산을 할 수 없습니다. 따라서 형변환을 해줘야지 오류가 안나는 것이지요.
비교 연산자
비교 연산자의 연산결과는 true 또는 false 중 하나입니다! 마찬가지로 이항연산자라 피연산자의 타입이 다를 경우 더 큰 쪽으로 자동 형변환을 해준답니다.
- 대소비교 연산자: >, <, <=, >=
- 등가비교 연산자: ==, !=
참고로 문자열을 비교할 때는, == 대신 equals()라는 메서드를 사용해야합니다! 그 이유는 String은 기본형이 아닌 참조형이기 때문입니다.
논리 연산자
'x가 4보다 작다'라는 조건은 x<4 처럼 간단하게 표현이 가능합니다. 그렇다면 'x가 4보다 작거나 또는 10보다 크다' 와 같이 두 개의 조건이 결합된 경우는 어떻게 표현해야 할까요? 이럴 때 사용하는 것이 논리 연산자입니다. 논리 연산자는 둘 이상의 조건을 AND, OR로 연결하여 하나의 식으로 표현할 수 있게 해줍니다.
- || (OR): 피연산자 중 하나만 true여도 true 반환
ex) x가 4보다 작거나 또는 10보다 크다: x<4 || x>10 - && (AND): 피연산자 중 모두 true여야 true 반환
ex) x가 2보다 크고, 6보다 작거나 같다: x>2 && x<=6 - ! (논리 부정 연산자): 피연산자가 ture이면 false, false이면 true를 반환
비트 연산자
비트 연산자는 피연산자를 비트단위로 연산하는 것을 말합니다.
- | (OR): 피연산자 중 한 쪽의 값만 1이어도, 1 반환
- &(AND): 피연산자 중 모두 1이면, 1 반환
- ^(XOR): 피연산자의 값이 서로 다를 때 1, 같으면 0 반환
- ~(비트 전환 연산자): 피연산자를 2진수로 표현했을 때, 0은 1로, 1은 0으로 변환
- <<, >> (쉬프트 연산자): 피연산자를 2진수로 표현했을 때 오른쪽(>>) 혹은 왼쪽(<<)으로 이동시킨후 그 값을 반환
그 외 연산자
- 조건 연산자(=삼항 연산자): 다음과 같이 사용할 수 있습니다.
'도서 정리 > 자바의 정석' 카테고리의 다른 글
[자바의 정석] CH06 객체지향 프로그래밍Ⅰ (2) (2) | 2025.04.09 |
---|---|
[자바의 정석] CH06 객체지향 프로그래밍Ⅰ (1) (2) | 2025.04.07 |
[자바의 정석] CH05 배열 정리 (0) | 2025.04.04 |
[자바의 정석] CH04 조건문과 반복문 정리 (0) | 2025.04.03 |
[자바의 정석] CH01-02 정리 (1) | 2025.04.01 |