팀 코드리뷰 시간에 비트 연산자로만 알고 있었던 |와 &를 논리 연산자처럼 사용할 수 있다는 말에 호기심을 가지게 되었습니다.
"어떻게 가능할까? 그리고 논리 연산자인 ||, &&와는 어떤 차이가 있을까?”라는 궁금증이 생겨서 정리해 보았습니다.
비트 연산자
|와 &는 비트 연산자입니다.
- |
"0001 | 0000 == 0001”이 성립합니다. 즉, 하나의 비트 비교시 하나라도 1이라면 1이 됩니다. - &
|와는 다르게 두 비트 모두가 1인 경우만 1이 됩니다.
즉, "0101 & 0100 == 0100”이 됩니다.
논리 연산자
|| 와 &&는 논리 연산자입니다.
- ||(or)
하나라도 true인 경우 true를 반환합니다. 즉, “true || false == true”가 됩니다. - &&(and)
모두 true인 경우만 true를 반환합니다. 즉, “true && true == true, true && false == false”가 됩니다.
비트 연산자를 논리 연산자로 사용
Java에서는 비트 연산자를 논리 연산자로 사용이 가능합니다.
public class OrOperationExample {
public static void main(String[] args) { if (alwaysFalse() | alwaysTrue()) { System.out.println("false | true case"); } System.out.println(); if (alwaysTrue() | alwaysFalse()) { System.out.println("true | false case"); } System.out.println(); if (alwaysFalse() || alwaysTrue()) { System.out.println("false || true case"); } System.out.println(); if (alwaysTrue() || alwaysFalse()) { System.out.println("true || false case"); } System.out.println(); } public static boolean alwaysTrue() { System.out.println("Always True"); return true; } public static boolean alwaysFalse() { System.out.println("Always False"); return false; } } |
public class AndOperationExample {
public static void main(String[] args) { if ((alwaysFalse() & alwaysTrue()) == false) { System.out.println("false & true case"); } System.out.println(); if ((alwaysTrue() & alwaysFalse()) == false) { System.out.println("true & false case"); } System.out.println(); if ((alwaysFalse() && alwaysTrue()) == false) { System.out.println("false && true case"); } System.out.println(); if ((alwaysTrue() && alwaysFalse()) == false) { System.out.println("true && false case"); } System.out.println(); } public static boolean alwaysTrue() { System.out.println("Always True"); return true; } public static boolean alwaysFalse() { System.out.println("Always False"); return false; } }
|
Always False
Always True
false | true case
Always True
Always False
true | false case
Always False
Always True
false || true case
Always True
true || false case
|
Always False
Always True
false & true case
Always True
Always False
true & false case
Always False
false && true case
Always True
Always False
true && false case
|
Java에서 실행결과를 보면 |와 ||, &와 &&는 같은 결과값을 가지는 것을 알 수 있습니다.
Java에서 비트 연산자를 논리 연산자로 사용할 수 있는 이유
Java에서 if문에는 boolean(또는 Boolean) 타입만 조건으로 사용할 수 있습니다.
|와 &를 if문에서 사용할 수 있는 이유는 위에서 테스트한 코드에서 알 수 있듯이 결과 값이 ||와 &&를 사용했을 때와 값이 같기 때문입니다.
00000001(true) | 00000000(false) == 00000001(true)
00000001(true) & 00000000(false) == 00000000(false)
true || false == true
true && false == false
|
C나 C++에서는 Java처럼 사용할 수 없는데요. 그 이유는 아래와 같습니다.
if(int & int) 구문에서 int 값이 양수이면 참, 0이면 false라고 예상이 될텐데, if(2&4)의 경우 "100 & 010 == 000"이 되기 때문에 false가 되기 때문에 사용할 수 없습니다. 다만 if(bool & bool)이라면 사용은 가능합니다.
비트 연산자(|, &) VS 논리 연산자(||, &&)
Java에서는 두 연산자에 대한 결과가 같기 때문에 비트 연산자를 논리 연산자로 사용할 수 있음을 샘플코드로 확인하였습니다.(위 코드 참조)
그렇다면 동작방식도 같을까요? 샘플코드의 결과 값을 확인해 보면 차이가 있음을 알 수 있습니다.
예를 들어 alwaysTrue() | alwaysFalse()와 alwaysTrue() || alwaysFalse()를 비교해 보겠습니다.
Always True
Always False
true | false case
|
Always True
true || false case
|
비트 연산자에서는 alwaysFalse()가 실행되었으나, 논리 연산자에서는 alwaysFalse()가 실행되지 않았습니다.
Or(||) 연산자의 경우 하나라도 True라면 결과 값이 True이기 때문에 첫번째 조건이 True라면 두 번째 조건과는 상관없이 True이기 때문에 Java에서는 비교 구문을 실행하지 않게 됩니다. 종합해 보면 비트 연산자의 경우는 조건문을 다 수행한다면 논리 연산자는 결과에 영향을 주지 않는다면 실행하지 않음을 알 수 있습니다.
alwaysTrue() || alwaysFalse()에서 alwaysFalse() 구문을 실행하지 않는 것을 Short-circuit(https://en.wikipedia.org/wiki/Short-circuit_evaluation)이라고 합니다.
참고
- https://en.wikipedia.org/wiki/Short-circuit_evaluation
- http://stackoverflow.com/questions/8759868/java-logical-operator-short-circuiting
'Programing > Java' 카테고리의 다른 글
Mybatis에서 resultType에 Primitive Type은 괜찮을까? (0) | 2016.10.04 |
---|---|
Java Collection Framework (0) | 2016.09.30 |
IBATIS CacheModel (0) | 2016.09.26 |
Exception Propagation (0) | 2016.07.28 |
Java 로그에서 StackTrace 가 생략되는 현상 (0) | 2016.04.04 |