Notice
Recent Posts
Recent Comments
Link
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

기록하자..

자바가 제공하는 다양한 연산자 | 백기선님 LIVE-STUDY 본문

자바

자바가 제공하는 다양한 연산자 | 백기선님 LIVE-STUDY

P23Yong 2022. 3. 24. 10:51

학습할 것

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

산술 연산자

연산자 피연산자 수 산출 값 설명
+ 이항 숫자 덧셈 연산
- 이항 숫자 뺄셈 연산
* 이항 숫자 곱셈 연산
/ 이항 숫자 좌측 피연산자를 우측 피연산자로 나눗셈 연산
% 이항 숫자 좌측 피연산자를 우측 피연산자로 나눈 나머지를 구하는 연산

자바에는 다음가 같은 산술 연산자들이 있다. 산술 연산자의 경우 숫자 타입(byte, short, int, long, float, double)으로 결과가 나온다.

사용법을 보자.

int a = 4;
int b = 5;

System.out.println("a + b: " + (a + b));
System.out.println("a - b: " + (a - b));
System.out.println("a * b: " + (a * b));
System.out.println("a / b: " + (a / b));
System.out.println("a % b: " + (a % b));
a + b: 9
a - b: -1
a * b: 20
a / b: 0
a % b: 4

비트 연산자

비트 연산자는 데이터를 비트 단위로 연산한다. 주의할 점은 실수 타입인 float, double은 비트 연산이 불가능하다는 것이다. 비트 연산자는 기능에 따라 비트 논리 연산자(&, |, ^, ~)와 비트 이동 연산자(<<, >>, >>>)로 구분한다.

비트 논리 연산자
| 연산자 | 피연산자 수 | 산출 값 | 설명 |
| ----- | ------- | ----- | --- |
| & | 이항 | 숫자 | 두 비트 모두 1일 경우에만 연산 결과가 1
| | | 이항 | 숫자 | 두 비트 중 하나만 1이면 연산 결과가 1
| ^ | 이항 | 숫자 | 두 비트 중 하나는 1이고 다른 하나가 0일 경우 연산결과가 1
| ~ | 단항 | 숫자 | 보수

사용법을 보자.

int a = 3;  // 0000 0011
int b = 4;  // 0000 0100

System.out.println("a & b: " + (a & b));
System.out.println("a | b: " + (a | b));
System.out.println("a ^ b: " + (a ^ b));
System.out.println("~a: " + ~a);
System.out.println("~b: " + ~b);
a & b: 0
a | b: 7
a ^ b: 7
~a: -4
~b: -5

비트 연산자는 피연산자를 int 타입으로 자동 타입 변환한 후 연산을 수행하게 된다. 그렇기에 비트 연산의 결과 타입은 int 타입이 된다.

비트 이동 연산자
| 연산자 | 피연산자 수 | 산출 값 | 설명 |
| ----- | ------- | ----- | --- |
| << | 이항 | 숫자 | 왼쪽 정수의 각 비트를 오른쪽 정수의 수만큼 왼쪽으로 이동시킨다.
| >> | 이항 | 숫자 | 왼쪽 정수의 각 비트를 오른쪽 정수의 수만큼 오른쪽으로 이동시킨다.
| >>> | 이항 | 숫자 | 왼쪽 정수의 각 비트를 오른쪽 정수의 수만큼 오른쪽으로 이동시킨다.

        /*
            00000000 00000000 00000000 00000001
            000은 버림
            00000000 00000000 00000000 00001000
         */
        System.out.println(1 << 3);

        /*
            11111111 11111111 11111111 11111000
            빈공간을 1로 채우고, 0은 버림
            11111111 11111111 11111111 11111111
         */
        System.out.println(-8 >> 3);

        /*
            11111111 11111111 11111111 11111000
            빈공간을 무조건 0으로 채우고, 0은 버림
            00011111 11111111 11111111 11111111
         */
        System.out.println(-8 >>> 3);
8
-1
536870911

>> 연산자는 비트를 오른쪽으로 밀게되는데 이때 빈공간을 최상위 부호 비트와 동일한 값으로 채우게 된다.

반면 >>> 연산자는 빈자리를 0으로 채우게된다.

관계 연산자

연산자 피연산자 수 산출 값 설명
== 이항 boolean 두 개의 항이 같으면 참, 다르면 거짓을 반환한다.
!= 이항 boolean 두 개의 항이 다르면 참, 같으면 거짓을 반환한다.
> 이항 boolean 왼쪽에 있는 항이 더 크면 참, 그렇지 않으면 거짓을 반환한다.
< 이항 boolean 오른쪽에 있는 항이 더 크면 참, 그렇지 않으면 거짓을 반환한다.
>= 이항 boolean 왼쪽에 있는 항이 더 크거나 같으면 참, 그렇지 않으면 거짓을 반환한다.
<= 이항 boolean 오른쪽에 있는 항이 더 크거나 같으면 참, 그렇지 않으면 거짓을 반환한다.
System.out.println("1 == 1: " + (1 == 1));
System.out.println("2 != 2: " + (2 != 2));
System.out.println("1 > 3: " + (1 > 3));
System.out.println("1 < 3: " + (1 < 3));
System.out.println("2.3 >= 2: " + (2.3 >= 2));
System.out.println("3.1 <= 3: " + (3.1 <= 3));
1 == 1: true
2 != 2: false
1 > 3: false
1 < 3: true
2.3 >= 2: true
3.1 <= 3: false

관계연산자는 비교연산자로, boolean 값인 true와 false를 반환한다.

논리 연산자

연산자 피연산자 수 산출 값 설명
&& 또는 & 이항 boolean 피연산자 모두가 true일 경우에만 true를 반환한다.
|| 또는 | 이항 boolean 피연산자 중 하나만 true이면 true를 반환한다.
! 단항 boolean 피연산자의 논리 값을 바꾼다.
System.out.println("true && false: " + (true && false));
System.out.println("true && true: " + (true && true));
System.out.println("true || false: " + (true || false));
System.out.println("true || true: " + (true || true));
System.out.println("false || false: " + (false || false));
System.out.println("!true: " + !true);
System.out.println("!false: " + !false);
System.out.println("!false: " + !false);
true && false: false
true && true: true
true || false: true
true || true: true
false || false: false
!true: false
!false: true

논리 연산자는 비트 연산과 비슷하지만 피연산자가 boolean 타입의 논리 값이다.

instanceof

instanceof 연산자는 이항연산자로, 객체가 주어진 타입이 맞는지 검사하는 연산자이다. instanceof 연산자의 결과는 boolean값인 true, false가 나오게된다.

static class Parent {

}

interface Shape {

}

static class Child extends Parent implements Shape {

}

public static void main(String[] args) {

    Child child = new Child();
    boolean result = child instanceof Parent;
    boolean result2 = child instanceof Shape;

    System.out.println(result);
    System.out.println(result2);
    System.out.println(null instanceof Parent);
}
true
true
false

instanceof 연산자는 is-a관계의 원리에 의해 동작한다. is-a관계는 상속이나 인터페이스 구현에 기반을 두고 있다. 위의 코드를 보면 Parent를 상속받고 Shape를 구현하고 있는 Child 클래스가 Parent와 Shape의 인스턴스인 것을 확인할 수 있다.

참고로 null은 어떤 것의 인스턴스도 아니라는 것을 기억해두자.

assignment(=) operator

연산자 피연산자 수 설명
= 이항 우측 피연산자의 값을 좌측 변수에 저장한다.

assignment operator, 대입 연산자는 오른쪽 피연산자의 값을 좌측 피연산자 변수에 저장하는 연산자이다. 기본적인 형태는 다음과 같다.

x = 1;
x = y = z = 1;
x (operator)= y;

x(operator)= y; 는 정해진 연산(operator)을 수행한 후 결과를 변수에 저장한다.

  • 대입 연산자 사용시 주의할 점이 하나 있는데, 피연산자가 reference type 일 경우 주소 값을 할당한다는 것을 주의해야 한다.
int x, y, z;
A a1 = new A();
A a2 = new A();

x = 1;
System.out.println("x = " + x);

x = y = z = 3;
System.out.println("x = " + x + ", y = " + y + ", z = " + z);

System.out.println("a1 = " + a1);
System.out.println("a2 = " + a2);

// reference type에 대입 연산자 사용시 주소 값 할당에 주의!
a1 = a2;
System.out.println("a1 = " + a1);
x = 1
x = 3, y = 3, z = 3
a1 = A@62043840
a2 = A@5315b42e
a1 = A@5315b42e

화살표(->) 연산자

화살표 연산자는 Java8부터 지원하는 람다식의 문법 중 일부이고, 함수의 몸체로 부터 파라미터를 분리한다. 익명함수의 매개변수와 리턴변수를 통해 만들어지는데, 익명함수를 접어 간결하게 표현하기 위해 사용한다.

(argument, ...) -> { expression }

Runnable 인터페이스를 익명 함수를 통해 구현한 모습을 살펴보자.

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Runnable.run()");
    }
};

다음과 같은 익명함수가 있을 때 화살표 연산자를 통해 줄일 수 있다.

Runnable runnable = () -> System.out.println("Runnable.run()");

3항 연산자

삼항 연산자는 세 개의 피연산자를 필요로 하는 연산자를 말한다. ? 앞의 조건식과 : 앞뒤의 피연산자가 선택된다.

조건식 ? (값 또는 연산식) : (값 또는 연산식)

조건식을 연산했을 때 true가 나오게 되면 콜론(:) 앞 연산식이, false가 나오면 콜론(:) 뒤 연산식이 실행된다.

String result;
int score = 80;

result = score > 70 ? "good" : "bad";
System.out.println("result = " + result);
result = good

연산자 우선 순위

위의 연산자들을 한 문장안에 사용했을 때는 어떤 순서로 실행이 될까? 각 연산자에는 우선순위가 있는데, 다음과 같다.

연산자 우선순위
expr++ expr-- 1
++expr --expr +expr -expr ~ ! 2
* / % 3
+ - 4
<< >> >>> 5
< > <= >= instanceof 6
== != 7
AND & 8
^ 9
| 10
&& 11
|| 12
? : 13
= += -= *= /= %= &= ^= |= <<= >>= >>>= 14

(optional) Java 13. switch 연산자

Java13 부터 변경된 내용이 하나 있는데, switch 연산자이다. break문을 사용하지 않고 화살표 연산자를 통해 표현할 수 있다.

switch(value) {
    case 1:
        result = 1;
        break;
    case 2:
        result = 2;
        break;
    case 3:
        result = 3;
        break;
    default:
        result = 4;
        break;
} 

이를 화살표 연산자를 통해 바꿀 수 있다.

switch(value) {
    case 1 -> result = 1;
    case 2 -> result = 2;
    case 3 -> result = 3;
    default -> result = 4;
} 

또 switch 연산자를 통해 값을 반환받을 수도 있다.

int result = switch(value) {
    case 1 -> 1;
    case 2 -> 2;
    case 3 -> 3;
    default -> 4;
}

또 한 가지 재미있는 점은 yield를 통해 산출값을 리턴할 수 있다. break를 통해 하던 것을 간결하게 바꿔준 느낌이다.

int result = switch(value) {
    case 1:
        yield 1;
    case 2:
        yield 2;
    case 3:
        yield 3;
    default:
        yield 4;
}

참고자료

이것이 자바다

밸덩 - instanceof

연산자 우선순위

자바 switch 연산자