[Java] 논리 연산자와 그 외 연산자
1️⃣ 논리 연산자
논리 연산자 '&&'는 '그리고(AND)'에 해당하며, 두 피연산자가 모두 true일 때만 true를 결과로 얻는다.
'||'는 '또는(OR)'에 해당하며, 두 피연산자 중 어느 한쪽만 true여도 true를 결과로 얻는다.
그리고 논리 연산자는 피연산자로 boolean형 또는 boolean형 값을 결과로 하는 조건식만을 허용한다.
💥 '|'는 한글 키보드에서 Enter키 위에 shift를 누른 상태에서 누르면 사용할 수 있다.
논리 연산자의 피연산자가 '참(true)인 경우'와 '거짓(false)인 경우'의 연산결과를 표로 나타내면,
x | y | x||y | x&&y |
true | true | true | true |
true | false | true | false |
false | true | true | false |
false | false | false | false |
일단은 책에서 활용된 예시들을 간단하게 정리하면 아래와 같이 사용하면 된다.
✅ ~~ 이고 ~~ 고 : &&
✅ 또는 : ||
헌데 예시 중 하나를 살펴보도록 하자.
➡ i는 2의 배수 또는 3의 배수지만 6의 배수는 아니다.
이와 같은 경우는 논리 연산자를 어떻게 활용하여서 묶는 것이 좋을까?
일단 i는 2의 배수 또는 3의 배수를 작성하면,
i%2 == 0 || i%3 == 0
그리고 뒤에 나오는 6의 배수는 아니다를 작성하면,
i%6 != 0
마지막으로 ~~지만으로 묶여있으므로 &&(AND)로 묶어주면 된다.
(i%2 == 0 || i%3 == 0) && i%6 != 0
짚고 넘어갈 것이 있다면 괄호를 사용한 이유는 '&&'보다 '||'이 우선순위가 낮기 때문이다. 만일 괄호를 사용하지 않으면 '&&'을 먼저 연산해 버린다.
✅ 이처럼 하나의 식에서 '&&'와 '||'가 같이 사용된 경우는 괄호를 사용해주어 우선순위를 명확하게 해주는 것이 좋다.
💥 효율적인 연산(short circuit evaluation)
논리 연산자의 특징 중 효율적인 연산을 할 수 있는 것에 대해서도 나와있다.
OR연산의 경우, 두 피연산자 중 어느 한 쪽만 '참'이어도 전체 결과가 '참'이므로 좌측 피연산자가 'true(참)'이면, 우측 피 연산자의 값은 평가하지 않는다.
AND연산의 경우도 마찬가지로 한쪽만 '거짓(false)이어도 전체 연산결과가 '거짓'이므로 좌측 피연산자가 '거짓'이면, 우측 피연산자는 평가하지 않는다.
✅그래서 같은 조건식이라도 피연산자의 위치에 따라서 연산속도가 달라질 수 있는 것이다.
예를 들어, OR연산 '||'의 경우에는 연산결과가 '참'일 확률이 높은 피연산자를 연산자의 왼쪽에 놓아야 더 빠른 결과를 얻을 수 있다.
2️⃣ 논리 부정 연산자 '!'
이 연산자는 피연산자가 true이면 false를, false이면 true를 결과로 반환한다. 간단하게 말해서, true와 false를 반대로 바꾸는 것이다. 연산결과를 표로 나타내면,
x | !x |
true | false |
false | true |
어떤 값에 논리 부정 연산자 '!'를 계속 적용하게 되면, 참과 거짓이 차례대로 반복이 된다.
이 연산자와 같은 성질을 이용하면 한번 누를 때 켜지고 다시 한번 누르는 TV의 전원버튼과 같은 '토글 버튼(toggle button)'을 논리적으로 구현할 수 있다.
3️⃣ 조건 연산자 ? :
조건식, 식1, 식2 모두 세 개의 피연산자를 필요로 하는 삼항 연산자이며, 삼항 연산자는 조건 연산자 하나뿐이다.
구조는 다음과 같이 되어 있다.
그림출처 : https://thebook.io/006989/ch04/07/
가독성을 높이기 위해 조건식을 괄호()로 둘러싸는 경우가 많지만 필수는 아니다.
조건 연산자는 조건문인 if문으로 바꿔 쓸 수 있으며, if문 대신 조건 연산자를 사용하면 코드를 보다 간단히 할 수 있다.
아래의 조건 연산자가 쓰인 문장을
result = (x > y) ? x : y;
if문으로 바꾸면 다음의 아래와 같다.
if (x > y)
result = x; // x > y가 true일 때
else
result = y; // x > y가 false일 때
특징을 살펴보면 else if와 같이 결과가 증가하게 되면 조건 연산자를 쓸 수 없다.
또한, 조건 연산자를 여러 번 중첩하면 코드가 간략해지지만 가독성이 떨어지므로 꼭 필요한 경우에 한번 정도만 중첩하는 것이 좋다.
4️⃣ 대입 연산자 =, op=
변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용된다.
이 연산자는 오른쪽 피연산자의 값을 왼쪽 피연산자에 저장한다. 그리고 저장된 값을 연산결과로 출력한다. 다음 아래와 같이 사용할 수 있다.
System.out.println(x = 3);
System.out.println(3); //위에서는 변수에 3이 저장되고 연산결과인 3이 출력된다.
대입 연산자는 연산자들 중에서 가장 낮은 우선순위를 가지고 있기 때문에 식에서 제일 나중에 수행된다. 그리고 연산 진행방향이 오른쪽에서 왼쪽이기 때문에 아래의 코드는
x = y = 3;
'y = 3' 그 다음에 ' x = y'가 수행된다.
✅ lvalue와 rvalue
대입연산자의 왼쪽 피연산자를 'lvaue(left value)'라고 하고, 오른쪽 피연산자를 'rvalue(right value)'라고 한다.
대입연산자의 rvalue는 변수뿐만 아니라 식이나 상수 등이 모두 가능한 반면, lvalue는 반드시 변수처럼 값을 변경할 수 있는 것이어야한다.
그래서 리터럴이나 상수같이 값을 저장할 수 없는 것들은 lvalue가 될 수 없다. 예시들을 보면
int i = 0;
3 = i + 3; // error lvalue가 값을 저장할 수 있는 공간이 아님
i + 3 = i; // error lvalue의 연산결과는 리터럴(i+3 -> 0+3 -> 3)
final int MAX = 3; // 변수 앞에 키워드 final을 붙이면 상수가 된다.
MAX = 10; // error 상수(MAX)에 새로운 값을 저장할 수 없다.
잘 보아야할 것은 final을 붙이면 상수가 되므로 상수에 한 번 저장된 값은 바꿀 수 없다.
💥 복합 대입 연산자
대입 연산자는 다른 연산자(op)와 겨랍하여 'op='와 같은 방식으로 사용될 수 있다.
예를 들어 'i = i - 5'은 'i -= 5'와 같이 표현될 수 있다. 결합된 두 연산자는 반드시 공백없이 붙여서 사용한다.
출처 : https://slidesplayer.org/slide/15044439/
참고문헌 -
자바의 정석 3판 남궁성 지음