관리 메뉴

개발그래머

[자바스터디 3주차] 연산자 본문

Java

[자바스터디 3주차] 연산자

임요환 2023. 5. 13. 21:10

목표

  • 자바가 제공하는 다양한 연산자를 학습

학습할 것

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

산술 연산자

  • 사칙연산을 다루는 연산자
  • 가장 기본적이며 가장 많이 사용되는 연산자
  • 두 개의 피연산자를 가지는 이항 연산자이며 피연산자들의 결합 방향은 왼쪽에서 오른쪽임
연산자 설명
+ 왼쪽의 피연산자에 오른쪽의 피연산자를 더함
- 왼쪽의 피연산자에서 오른쪽의 피연산자를 뺌
* 왼쪽의 피연산자에 오른쪽의 피연산자를 곱함
/ 왼쪽의 피연산자를 오른쪽의 피연산자로 나눔
% 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후 그 나머지를 반환
int x = 10;
int y = 5;

System.out.println(x + y);// 15
System.out.println(x - y);// 5
System.out.println(x * y);// 50
System.out.println(x / y);// 2
System.out.println(x % y);// 0
System.out.println(y + x);// 15
System.out.println(y - x);// -5
System.out.println(y * x);// 50
System.out.println(y / x);// 0
System.out.println(y % x);// 5
  • 나누기와 곱하기 연산 방식은 비트를 shift하며 계산을 하기 때문에 몫과 나머지를 구하는데 최적화 되어있음

비트 연산자

  • 논리 연산자와 비슷하지만, 비트 단위로 논리 연산을 할 때 사용함
  • 비트 단위로 왼쪽이나 오른쪽으로 전체 비트를 이동하거나 1의 보수를 만들 때 사용함
연산자 설명
& 대응되는 비트가 모두 1이면 1을 반환(비트 AND 연산)
| 대응되는 비트 중에서 하나라도 1이면 1을 반환(비트 OR 연산)
^ 대응되는 비트가 서로 다르면 1을 반환(비트 XOR 연산)
~ 비트를 1이면 0으로, 0이면 1로 반전시킴(비트 NOT 연산, 1의 보수)
<< 명시된 수만큼 비트들을 전부 왼쪽으로 이동(left shift 연산)
>> 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동(right shift 연산)
>>> 지정한 수만큼 비트를 전부 오른쪽으로 이동, 새로운 비트는 전부 0
int x = 8;
int y = 2;

System.out.println(x & y);// 0
System.out.println(x | y);// 10
System.out.println(x ^ y);// 10
System.out.println(~x);// -9
System.out.println(x << y);// 32
System.out.println(x >> y);// 2
System.out.println(x >>> y);// 2
int start = 2100000000;
int end = 2100000000;

int mid = (start + end) / 2; // 오버플로우가 날 수 있는 코드
System.out.println(mid); // -47483648 -> 이상한 숫자가 나옴

int mid2 = start + (end - start) / 2; // 안전한 코드
System.out.println(mid2); // 2100000000

int mid3 = (start + end) >>> 1; // 안전한 코드(비트 연산자 이용), 양수에서만 가능
System.out.println(mid3); // 2100000000
public class OperatorTest {
    // TODO numbers라는 int형 배열이 있다.
    // 해당 배열에 들어있는 숫자들은 오직 한 숫자를 제외하고는 모두 두번씩 들어있다.
    // 오직 한 번만 등장하는 숫자를 찾는 코드를 작성하라.
    public static void main(String[] args) {
        Solution solution = new Solution();
        int result = solution.calculate(new int[] {5,2,4,10,2,4,5});
        System.out.println(result);
    }

    //TODO XOR 연산 사용
    private static class Solution {
        int calculate(int[] numbers){
            int result = 0;
            for (int number : numbers) {
                result ^= number;
            }
            return result;
        }
    }
}

관계 연산자

  • 비교 연산자라고도 부름
  • 피연산자 사이의 상대적인 크기를 판단하는 연산자
  • 왼쪽의 피연산자와 오른쪽의 피연산자를 비교하여 어느 쪽이 더 큰지, 작은지, 또는 서로 같은지를 판단함
  • 모두 두개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽임
연산자 설명
== 왼쪽의 피연산자와 오른쪽의 피연산자가 같으면 참을 반환
!= 왼쪽의 피연산자와 오른쪽의 피연산자가 같지 않으면 참을 반환
> 왼쪽의 피연산자가 오른쪽의 피연산자보다 크면 참을 반환
>= 왼쪽의 피연산자가 오른쪽의 피연산자보다 크거나 같으면 참을 반환
< 왼쪽의 피연산자가 오른쪽의 피연산자보다 작으면 참을 반환
<= 왼쪽의 피연산자가 오른쪽의 피연산자보다 작거나 같으면 참을 반환
int x = 8;
int y = 2;

System.out.println(x == y);// false
System.out.println(x != y);// true
System.out.println(x > y);// true
System.out.println(x >= y);// true
System.out.println(x < y);// false
System.out.println(x <= y);// false

논리 연산자

  • 주어진 논리식을 판단하여 true와 false을 결정함
  • AND 연산과 OR 연산은 두개의 피연산자를 가지는 이항 연산자이며 피연산자들의 결합 방향은 왼쪽에서 오른쪽임
  • NOT 연산자는 피연산자가 단 하나뿐인 단항 연산자이며 피연산자의 결합 방향은 오른쪽에서 왼쪽임
연산자 설명
&, && 논리식이 모두 참이면 참을 반환(논리 AND 연산)
|, || 논리식 중에서 하나라도 참이면 참을 반환(논리 OR 연산)
! 논리식의 결과가 참이면 거짓을, 거짓이면 참을 반환(논리 NOT 연산)

A B A & B A | B !A
true true true true false
true false false true false
false true false true true
false false false false true
int x = 0;
int y = 0;
if(x++ == 0 || y++  == 0){
    System.out.println("plus");
}

System.out.println(x); // x = 1
System.out.println(y); // y = 0

int x = 0;
int y = 0;
if(x++ == 0 | y++  == 0){
    System.out.println("plus");
}

System.out.println(x); // x = 1
System.out.println(y); // y = 1

// ||, && 과 |, & 의 차이는 ||은 첫번째 조건식 검사후 이게 맞으면 
// 두번째 조건식은 건너뛰어 불필요한 연산을 줄이고 효율적으로 실행시키지만
// |는 모든 조건식을 전부 실행시킴

instanceof

  • 참조 변수가 참조하고 있는 인스턴스의 실제 타입을 반환
  • 해당 객체가 어떤 클래스나 인터페이스로부터 생성되었는지를 판별해 주는 역할
Integer x = 8;

System.out.println(x instanceof Object);// true
System.out.println(x instanceof Number);// true
System.out.println(x instanceof Comparable);// true

assigment(=) operator

  • 대입 연산자라고도 부름
  • 변수에 값을 대입할 때 사용하는 이항 연산자이며 피연산자들의 결합 방향은 오른쪽에서 왼쪽임
  • 자바에서 대입 연산자와 다른 연산자를 결합하여 만든 다양한 복합 대입 연산자를 제공함
연산자 설명
= 왼쪽의 피연산자에 오른쪽의 피연산자를 대입
+= 왼쪽의 피연산자에 오른쪽의 피연산자를 더한 후 그 결괏값을 왼쪽의 피연산자에 대입
-= 왼쪽의 피연산자에서 오른쪽의 피연산자를 뺀 후 그 결괏값을 왼쪽의 피연산자에 대입
*= 왼쪽의 피연산자에 오른쪽의 피연산자를 곱한 후 그 결괏값을 왼쪽의 피연산자에 대입
/= 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후 그 결괏값을 왼쪽의 피연산자에 대입
%= 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후 그 나머지를 왼쪽의 피연산자에 대입
&= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 AND 연산한 후 그 결괏값을 왼쪽의 피연산자에 대입
|= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 OR 연산한 후 그 결괏값을 왼쪽의 피연산자에 대입
^= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 XOR 연산한 후 그 결괏값을 왼쪽의 피연산자에 대입
<<= 왼쪽의 피연산자를 오른쪽의 피연산자만큼 왼쪽 시프트한 후 그 결괏값을 왼쪽의 피연산자에 대입
>>= 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호를 유지하며 오른쪽 시프트한 후 그 결괏값을 왼쪽의 피연산자에 대입
>>>= 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호에 상관없이 오른쪽 시프트한 후 그 결괏값을 왼쪽의 피연산자에 대입
int x;
int y = 4;

System.out.println(x = 10);// 10
System.out.println(x += y);// 14
System.out.println(x -= y);// 10
System.out.println(x *= y);// 40
System.out.println(x /= y);// 10
System.out.println(x %= y);// 2
System.out.println(x &= y);// 0
System.out.println(x |= y);// 4
System.out.println(x ^= y);// 0
System.out.println(x <<= y);// 0
System.out.println(x >>= y);// 0
System.out.println(x >>>= y);// 0

화살표(->) 연산자

  • Java8부터 람다 표현식이 등장하면서 도입된 문법
  • 익명 함수를 만들기 위해 사용
  • FunctionalInterface 메소드를 구현할 때 주로 사용
// 기본
(parameters) -> { statements; }

// 파라미터는 0개 이상
() -> { statements; }

// 파라미터가 1개면 ( ) 생략 가능
parameter -> { statements; }

// statements가 하나면 { } 생략 가능, 이때 ; 도 생략 가능
(parameters) -> statement

3항 연산자

  • 자바에서 유일하게 피연산자를 세 개나 가지는 조건 연산자
  • 조건식 ? 반환값1 : 반환값2 -> 조건식이 참이면 반환값1을 반환, 거짓이면 반환값2를 반환
int x = 8;
int y = 10;

System.out.println(x > y ? "진실" : "거짓");// 거짓

연산자 우선순위

  • 수식 내에 여러 연산자가 함께 등장할 때, 어느 연산자가 먼저 처리될 것인가를 결정함
우선순위 연산자 설명
1 (),[] 괄호, 대괄호
2 !,~,++,-- 부정, 증감 연산자
3 *,/,% 곱셈, 나눗셈 연산
4 +,- 덧셈, 빼기 연산
5 <<,>>,>>> 비트 단위 쉬프트 연산자
6 <.<=,>,>= 관계 연산자
7 ==,!= 관계 연산자
8 & 비트 단위 논리 연산자
9 ^ 비트 단위 논리 연산자
10 && 논리곱
11 || 논리합
12 ?: 조건부 연산자
13 =,+=,-=,*=,/=,%=,<<=,>>=,&=,^=,~= 대입 할당 연산자

(optional) Java 13.switch 연산자

  • Java12부터 switch 연산자가 추가됨
  • switch문의 변경이 아니라 새로운 switch 연산자가 추가된 것
//기존 스위치 문
String numStr = "One";
int result = 0;

switch(numStr){
    case "One":
        result = 1;
        System.out.println(1);
        break;
    case "Two":
        result = 2;
        System.out.println(2);
        break;
    case "Three":
        result = 3;
        System.out.println(3);
        break;
    default:
        System.out.println("default");
}
  • 기존 스위치 문은 불필요하게 장황하며 가독성이 떨어지며 디버깅이 어려워짐
//Java12 switch 연산자
String numStr = "One";
int result = 0;

result = switch (numStr) {
    case "One" -> 1;
    case "Two" -> 2;
    case "Three" -> 3;
    default -> throw new IllegalStateException("error");
}
  • Java12부터 람다 연산을 사용하여 가독성을 올릴 수 있음
//Java13 switch 연산자
String numStr = "One";
int result = 0;

result = switch(numStr) {
    case "One" : yield 1;
    case "Two" : yield 2;
    case "Three" : yield 3;
    default : throw new IllegalStateException("error");
};
  • Java13부터 yield라는 산출값을 리턴 가능함
  • break를 사용하지 않고 yield를 사용하여 변수에 값을 넣을 수 있음