비교 연산자라고도 하며 우리가 수학시간에 배웠던 부등호를 생각하시면 됩니다. 관계연산자의 결과는 true 혹은 false 값인 boolean 자료형으로 반환이 됩니다. 뒤에서 배울 제어문에서 많이 사용되는 연산자 입니다.
관계 연산자의 대부분의 연산자들은 수학의 연산자와 의미가 같고 '=='이 두항이 서로 같다는 의미에 연산자 이며 '!='(낫이꼴)이 두항이 서로 다르다는 뜻에 연산자입니다.
논리 연산자는 AND(&&), OR(||), NOT(!) 세가지의 연산자가 있으며 관계연산자와 같이 사용 되는 경우가 많습니다. 논리 연산자 역시 연산의 결과가 true 혹은 false로 반환 됩니다.
단락회로 평가는 논리 연산자를 사용할 때 고려해야 할 사항으로 두항 중 앞의 항에서 결과값이 정해지는 경우 뒤의 값이 참인지 거짓인지 평가하지 않는 것을 단락회로평가라고 합니다.
public class OperatorEx3 {
public static void main(String[] args) {
int num1 = 10;
int i = 2;
boolean value = ((num1 = num1 +10)<10) && ((i = i+2)<10);
//여기서는 num1은20이 됬고 i는 4가됬을거라고 생각 할 수 있음
System.out.println(num1); //20
System.out.println(i); //2 앞에만 봐도 평가가 뒤기때문에 평가를 하지 않아서 값은 2그대로이다..
System.out.println(value); //false
int num2 = 10;
int i2 = 2;
boolean value2 = ((num2 = num2 +10)<10) || ((i2 = i+2)<10);
System.out.println(num2); //20
System.out.println(i2); //4 // 이번엔 앞에가 false여도 뒤에까지 체크해야되기 때문에 4가됨
//만약 앞에가 true였다면 이번에도 계산안됨
System.out.println(value2); //true
// 이걸 단락회로평가라고 한다// 코딩할 때 주의할 것!
value를 논리곱을 이용하여 연산하는 과정에서 num1 항의 평가를 마치고 false라고 판단하면 뒤에 i항은 평가하지 않았기 때문에 num1은 평가가 반영된 20이지만 i는 평가가 반영되지 않은 i로 남아 있음을 확인할 수 있습니다.
value2를 논리합을 이용하여 연산하는 과정에서 num2가 false로 나왔지만 i항까지 평가해야 되기 때문에 두 변수 모두 평가가 평가가 되어 n2=20; i =4;라는 값이 나왔습니다. 만약 value2에서 i항이 먼저나와 ture가 나왔다면 앞의 value의 경우처럼 뒤에 num2항을 평가 하지 않았을 것 입니다.
이렇듯 실제프로그램에서 단락회로평가에 의해서 뒤의 항이 평가되지 않아 예상치 못한 결과 발생할 수 있으니 주의하여야 합니다.
조건 연산자는 유일한 삼항 연산자로 '조건식? 결과1: 결과2;' 이라는 간단한 구조로 되어 있고 조건식이 ture이면 결과1을 실행하고 false면 결과2를 실행하라는 조건문을 만들어내는 연산자 입니다.
package operator;
public class OperatorEx3 {
public static void main(String[] args) {
int num3=(5>3)? 10:20;
System.out.println(num3); // 10
int num4 = 10;
int num5 = 20;
int max = (num4 > num5)?num4:num5;
System.out.println(max); //20
}
}
위에 예제를 살펴보면 변수 num3에서 조건문이 참이기에 첫번째 결과값인 10이 대입되 었고 변수 max에서 조건문이 거짓이기에 뒤에 결과값이 나와 20이 대입 되었습니다. 이처럼 조건연산자는 간단한 조건문을 만들어 내는 연산자입니다.
비트연산자는 특정 비트를 사용하기위해 꺼내 올때 사용하고 다음과 같은 연산자들을 가지고 있습니다.
아래 예제를 통해 이 연산자들을 어떻게 사용하는지 살펴보겠습니다.
public class OperatorEx4 {
public static void main(String[] args) {
int num1 = 0B00001010 ; //10, 0B는 2진수시작부호
int num2 = 0B00000101; // 5
System.out.println(num1 & num2); //위아래 둘다 1일때 1 =00000000 = 0
System.out.println(num1 | num2 ); //둘중하나가 1일때 1 = 00001111 = 15
System.out.println(num1 ^ num2); // 두개가 다를때 1 = 00001111 = 15
System.out.println(num2 << 1); //num2 한칸씩왼쪽으로 = 00001010 = 10
System.out.println(num2 << 2); //num2 두칸씩왼쪽으로 = 00010100 = 20 // 여기까지 num2값 변하지 않음
System.out.println(num2 <<= 2); //대입연산자 쓰면 대입되서 바뀜
System.out.println(num2); // 10에서 20으로 변함
int num3 = 0B00000101; // 5
System.out.println(num3 >> 2); // 맨오른쪽칸 두개 없어짐 000001 = 1
System.out.println(num3 >> 1); // 맨오른쪽칸 두개 없어짐 0000010 = 2
//결국 나누기랑 같다, >>1은 /2에1승, >>2는 /2의2승
}
}
"&, | , ^" 연산자는 위의 예제처럼 두개의 비트를 비교하여 새로운 비트값이 나오게 되는데 이것을 통해 특정한 위치의 비트가 어떤 값을 가지고 있는지 알 수 있습니다.
"<<, >>"와 같은 shift 연산자를 쓰면 비트가 지정한 자리수만큼 이동하여 결과적으로 왼쪽으로 이동시(<<) 곱한 결과 값이 나오고 오른쪽으로 이동시(>>) 나눈 결과 값이 나오게 되며 '='대입 연산자와 함께 사용시 이동된 값이 변수에 대입이 됩니다.
위 예제에서 살펴보듯 비트 연산자는 특정한 위치의 비트를 찾아내어 활용하거나 비트를 곱하거나 나누는 용도로 활용할 수 있습니다.
참고로 자바의 연산자는 수학의 연산자 처럼 우선순위가 있습니다. 그 중 단항 우선자의 우선순위가 높은편이고 대입연산자(복합대입연산자 포함)의 우선순위가 가장 낮습니다.