본문 바로가기
Java

[자바 스터디] #3 - 연산자

by zannew 2021. 2. 4.

 목표

자바가 제공하는 다양한 연산자를 학습하세요.

▣ 학습할 내용

  • 산술 연산자
  • 비트 연산자
  • 관계 연산자
  • 논리 연산자
  • instanceof
  • assignment(=) operator
  • 화살표(->) 연산자
  • 3항 연산자
  • 연산자 우선 순위
  • (optional) Java 13. switch 연산자

 

▶ 3-0 용어 정리

연산자 (operator) : 연산을 수행하는 기호 (+, -, *, /, % 등)

피연산자(operand) : 연산자의 작업 대상 (변수, 상수, 리터럴, 수식 등)

 

▶ 3-1 산술 연산자(Arithmetic Operator)

기본 사칙 연산자(+, -, *, /)와 나머지 연산자(%)가 있다. 우선순위도 이미 알고있던 순서대로 곱셈, 나눗셈, 나머지 연산자의 우선순위가 높고, 덧셈과 뺄셈은 그 다음에 처리된다. 나눗셈의 경우 주의할 점은 나누는 피연산자가 정수형인 경우, 0으로 나누면 에러가 발생한다. (ArithmeticException 발생)

상대적으로 범위가 작은 타입의 연산도 주의해야한다. 아래 예시는 byte타입의 연산이다. 

public class Main {
    public static void main(String[] args) {
        byte a=10;
        byte b=20;
        byte c=a+b;		// 컴파일 에러 발생
        System.out.println(c);
    }
}

위의 코드는 컴파일 타임에 에러가 발생하기 때문에 아래 코드와 같이 명시적 형변환(Type Casting)이 필요하다. 단, 큰 자료형에서 작은 자료형으로 명시적 형변환을 할 때 값의 범위를 체크해야한다. 값의 범위를 넘어버리면 데이터 손실이 발생하여 정확한 결과 값을 얻을 수 없다. 반대로 작은 자료형에서 큰 자료형으로 변환하는 것은 데이터 손실이 발생하지 않는다. byte에서 int로 바뀐다면, bit 8자리는 그대로 보존하고 나머지 3byte(27bit)에 해당하는 자리는 0으로 채우게 된다.  

public class Main {
    public static void main(String[] args) {
        byte a=10;
        byte b=20;
        byte c=(byte)(a+b);		//OK!
        System.out.println(c);
    }
}

 

 

▶ 3-2 비트 연산자(Bitwise Operator)

 

▷ | (OR연산자) : 피연산자 중 한 쪽의 값이 1이면, 1을 결과로 얻는다. 그 외에는 0을 얻는다.

 & (AND연산자) : 피연산자 양 쪽이 모두 1이어야만 1을 결과로 얻는다. 그 외에는 0을 얻는다.

 ^ (XOR연산자) : 피연산자의 값이 서로 다를 때만 1을 결과로 얻는다. 같을 때는 0을 얻는다.

 

x y x | y x & y x ^ y
1 1 1 1 0
1 0 1 0 1
0 1 1 0 1
0 0 0 0 0

 

 비트 전환 연산자 '~' : 피연산자를 2진수로 표현했을 때, 0은 1로, 1은 0으로 바꾼다. 논리부정 연산자 '!'와 비슷하다.

x ~x
1 0
0 1

 

비트 전환 연산자에 의해 전환이 되고 나면, 부호있는 타입의 피연산자는 부호가 반대로 변경된다. (양수 -> 음수) 즉, 피연산자의 1의 보수를 얻을 수 있다. 그래서 비트 전환 연산자를 '1의 보수 연산자'라고도 부른다. 

	0 0 0 0 1 0 1 0	//10 
               ↓
	1 1 1 1 0 1 0 1	//-11

	   1 1 1 1 0 1 0 1
 	+  0 0 0 0 0 0 0 1 
 -----------------------------
 	1 1 1 1 0 1 1 0 //-10
    

 

위의 예시와 같이 10진수 10을 비트전환 연산한 결과는 -11이 된다. 그리고 이 값을 10의 '1의 보수'이다. 1의 보수에 1을 더하면 음수가 되므로 -11에 1을 더하면 -10이 되므로 -11은 10의 '1의 보수'가 됨을 확인할 수 있다.

비트 전환 연산자는 피연산자의 타입이 int보다 작으면 int로 자동형변환(Type Casting)한 후에 연산하기 때문에 연산결과는 32자리의 2진수가 된다.

 

 

▷쉬프트 연산자 '<<' OR '>>' : 피연산자의 각 자리(2진수로 표현했을 때)를 '오른쪽(>>)' 또는 '왼쪽(<<)'으로 이동한다고 하여 '쉬프트 연산자(shift operator)'라고 불린다.

예를 들어 8<<2 는 왼쪽 피연산자인 10진수 8의 2진수를 왼쪽으로 2자리 이동한다는 뜻이다. 반대로 8>>2는 2진수를 오른쪽으로 2자리 옮긴다는 의미이다. 

왼쪽 쉬프트 연산자의 경우를 먼저 보자면, 

1) 10진수 8을 2진수로 표현하면 '00001000'이 된다. 이 8의 2진수를 왼쪽으로 2자리 이동하고 나머지는 빈자리는 0으로 채운다.

0 0 0 0 1 0 0 0

2) 빈자리를 채운 빨간 숫자 0이 있고 범위를 벗어난 파란색 숫자 0이 있다. 범위를 벗어난 파란 숫자는 버려지고 빨간 숫자만 남는다.'8<<2'의 결과는 2진수로 '001000000'이 되고, 이 2진수를 다시 10진수로 변환하면 32가 된다. 

0 0 0 0 1 0 0 0 0 0

 

이제 오른쪽 쉬프트 연산자의 경우를 보자, 

1) 8의 2진수를 오른쪽으로 2자리 이동하고 나머지는 빈자리는 0으로 채운다. (단, 피연산자(여기서는 8)이 음수라면 빈자리를 1로 채운다.)

0 0 0 0 1 0 0 0

2) 빈자리를 채운 빨간 숫자 0이 있고 범위를 벗어난 파란색 숫자 0이 있다. 범위를 벗어난 파란 숫자는 버려지고 빨간 숫자만 남는다.'8<<2'의 결과는 2진수로 '001000000'이 되고, 이 2진수를 다시 10진수로 변환하면 32가 된다. 

0 0 0 0 0 0 1 0 0 0

식으로 편하게 외우려면,

x<<n은 x * 2^n의 결과와 같다.
x>>n은 x / 2^n의 결과와 같다.

로 외워두면 될 것 같다.

편하게 나눗셈, 곱셈할 수 있는데 왜 쉬프트 연산자를 제공할까? 속도에서 차이가 나기 때문이다. 가독성이 중요하다면 나눗셈, 곱셈 사용해도 되지만, 속도가 중요시되는 프로그램 개발에선 쉬프트 연산을 활용하는 것이 좋다.

 

▶ 3-3 관계 연산자(비교 연산자 : Comparison Operator)

관계 연산자는 자주 사용하니까 간단히 정리하고 넘어가야겠다.

 

▷ 대소비교 연산자

연산자 연산결과
> 좌변 값이 크면 true, 아니면 false
< 좌변 값이 작으면 true, 아니면 false
>= 좌변 값이 크거나 같으면 true, 아니면 false
<= 좌변 값이 작거나 같으면 true, 아니면 false

 

▷ 등가비교 연산자

연산자 연산결과
== 두 값이 같으면 true, 아니면 false
!= 두 값이 다르면 true, 아니면 false

 

▷ 문자열의 비교

두 문자열을 비교할 때는, 연산자 '==' 대신 equals()라는 메서드를 사용해야 한다. equals()는 비교하는 두 문자열이 같으면 true, 다르면 false를 리턴한다. 

문자열 비교

 

문자열 비교 결과

 

▶ 3-4 논리 연산자(Logical Operator)

|| (OR 결합) : 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻는다.
&& (AND 결합) : 피연산자 양쪽 모두 true이어야 true를 결과로 얻는다.

-------------------------------------------------------------------------------
! (논리 부정 연산자) : 피연산자가 true이면 false를, false이면 true를 리턴한다.


 

▶ 3-5 instanceof

참조변수 instanceof 타입(클래스명)
            
-> 연산의 결과로 true가 나온다는 것은 참조변수가 오른쪽 타입으로 형변환이 가능하다는 것을 의미한다.

 

▶ 3-6 Assignment(=) Operator

대입연산자라고도 불린다. 대입 연산의 진행방향은 오른쪽에서 왼쪽이기 때문에 'x=y=3;'에서 'y=3'이 먼저 수행되고 그 다음에 'x=y'가 수행된다. 

▷ 복합 대입 연산자

다른 연산자와 결합하여 '{op}='과 같은 방식으로 사용할 수 있다. 예를 들어 +=, -=, *=, /=, %=등 결합된 두 연산자는 공백없이 사용해야 한다. 풀어서 작성하면

i = i+3;
i = i-3;
i = i*3;
i = i/3;
i = i%3;

 

이렇게도 작성할 수 있다.

 

▶ 3-7 화살표 (->) 연산자

화살표 연산자는 람다식을 작성할 때 메서드이름과 반환타임을 제거하고 매개변수 선언부와 바디 사이에 '->'를 추가하는 방식으로 쓰인다.

-> 연산자 

 

▶ 3-8 3항 연산자

▶ 3-9 연산자 우선순위

 

▶ 3-10 (optional) Java 13, Switch Operator

기존의 swtich의 case : 에서 콜론이 빠지고 arrow operator을 사용할 수 있게 되었다. break대신 yield을 사용한다. 다중 구문 적용시, throw구문을 사용할 때, expression이 아닌 경우는 중괄호로 감싼다.

public class Test {
    public static void main(String[] args) {
        countNum(2);
    }
    public static void countNum(int i){
        switch(i){
            case 1 -> System.out.println("하나");
            case 2 -> System.out.println("둘");
            case 3 -> System.out.println("셋");
            default -> System.out.println("3이상 숫자");
        }
    }
}

 

 

 

 

백기선님의 자바 라이브 스터디 커리큘럼을 따라 공부하고 있습니다. 

잘못된 점이나 보충할 부분이 있으면 코멘트 남겨주세요

작은 조언이 저에겐 성장의 원동력이 됩니다 :-)

 

 

댓글