Study/java

[백기선님의 자바 라이브 스터디] 3주차 - 연산자

에디개발자 2020. 12. 27. 00:20
반응형

www.youtube.com/watch?v=HLnMuEZpDwU 

나를 닮았다고 한다...

목표

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

 

학습할 것

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

간단한 용어 정리

정리하기에 앞서 관련용어를 정리해보겠습니다.

연산 ( operations ) 프로그램에서 데이터를 처리하여 결과를 얻어내는 것
연산자 ( operator ) 연산에 사용되는 부호, 기호
피연산자 ( operand ) 연산에 대상이되는 데이터
연산식 ( expressions ) 피연산자와 연산자로 연산을 하는 과정
public void expressions() {
    // primitive type 변수 선언과 초기화
    int a = 1;
    int b = 2;
    
    int c = a + b;
    // 연산 : 위 코드가 연산
    // 연산자 : +
    // 피연산자 : a, b
    // 연산식 : a + b
}

산술 연산자

+, -, *, /, % 5가지로 구성되어있습니다.

마지막 %는 나머지값을 구하는 연산자로 Modulo라고 불립니다. 

간단한 코드로 살펴보겠습니다.

public static void 산술연산자() {
    int var1 = 1;
    int var2 = 2;

    System.out.println("var1 + var2 = " + (var1 + var2));
    System.out.println("var1 - var2 = " + (var1 - var2));
    System.out.println("var1 * var2 = " + (var1 * var2));
    System.out.println("var1 / var2 = " + (var1 / var2));
    System.out.println("var1 % var2 = " + (var1 % var2));

    double var3 = 1;
    double var4 = 2;
    System.out.println("var3 / var4 = " + (var3 / var4));
}

여기서 주의깊게 살펴보아야할 것은 나누기 연산에 대한 결과값입니다.

int 자료형을 사용했을 경우는 1 / 2 는 0.5라는 결과값이 나와야하지만 int 타입은 소숫점은 표현하지 않기 때문에 .5를 절삭하고 0이라는 결과값이 나왔습니다. 반면에 double 자료형을 사용하면 0.5라는 결과를 얻을 수 있습니다. 

피연산자의 자료형의 표현범위에 따라서 결과값이 다르게 나타납니다.

 

비트 연산자

& AND
| OR
^ XOR
>> Right Shift
<< Left Shift
public static void 비트연산자() {
    /**
     * int 자료형은 8 Byte이므로 32비트로 표현된다.
     * 0000 0000 0000 0000
     * 연산 설명을 편의를 위해 앞의 12자리는 제외하고 실제 값이 표현되는 마지막 4자리만 표현하겠습니다.
     */
    int var1 = 3;  // 0011
    int var2 = 5;  // 0101
    System.out.println("var1 & var2 = " + (var1 & var2));
    System.out.println("var1 | var2 = " + (var1 | var2));
    System.out.println("var1 ^ var2 = " + (var1 ^ var2));
    System.out.println("var1>> = " + (var1 >> 1));
    System.out.println("var1<< = " + (var1 << 1));
}

AND ( & )

AND 연산자는 같은 위치의 값 모두 1일 경우에 값이 1이 됩니다.

결과값으로 1 (0001) 이 나옵니다.

0 0 1 1
0 1 0 1
 
0 1 1 1

OR ( | )

OR 연산자는 같은 위치의 값 중 하나라도 1일 경우 값이 1이 됩니다.

결과값으로 7  (0001)이 나옵니다.

0 0 1 1
0 1 0 1
 
0 1 1 1

XOR ( ^ )

XOR 연산자는 같은 위치의 값 중 한개만 1이어야 1이 됩니다. 

결과값으로 6 ( 0110 )이 나옵니다.

0 0 1 1
0 1 0 1
 
0 1 1 0

Right Shift ( >> )

Right Shift 연산자는 값을 오른쪽으로 shift 시킵니다.

결과값으로 1이 나옵니다.

0 0 1 1
 
0 0 0 1

Left Shift ( << )

Lift Shift 연산자는 값을 왼쪽으로 shift 시킵니다.

결과값으로 6이 나옵니다.

0 0 1 1
   
0 1 1 0

 

관계 연산자

관계 연산자는 양쪽에 있는 데이터를 비교하는 연산자입니다.

== 양 쪽 데이터가 같으면 true, 다르면 false
!= 양 쪽 데이터가 같으면 false, 다르면 true
> 왼쪽 데이터가 오른쪽 데이터보다 크면 true, 작으면 false
< 왼쪽 데이터가 오른쪽 데이터보다 크면 false, 작으면 true
>= 왼쪽 데이터가 오른쪽 데이터보다 크거나 같으면 true, 작으면 false
<= 왼쪽 데이터가 오른쪽 데이터보다 작거나 같으면 true, 크면 false
instanceod 양 쪽 객체의 타입이 같으면 true, 다르면 false
public static void 관계연산자() {
    int var1 = 1;
    int var2 = 4;
    Account a = new Account();
    System.out.println("var1 == var2");
    System.out.println(var1 == var2);
    System.out.println("var1 != var2");
    System.out.println(var1 != var2);
    System.out.println("var1 > var2");
    System.out.println(var1 > var2);
    System.out.println("var1 < var2");
    System.out.println(var1 < var2);
    System.out.println("var1 <= var2");
    System.out.println(var1 <= var2);
    System.out.println("var1 >= var2");
    System.out.println(var1 >= var2);
    System.out.println("a instanceof Account");
    System.out.println(a instanceof Account);
}

instanceof는 밑에서 자세히 다루겠습니다.

논리연산자

논리연산자는 비트연산과 매우 흡사합니다. 차이점은 논리연산자의 피연산자는 boolean 타입입니다.

&& 양쪽 데이터 모두 true인 경우 true, 하나라도 false라면 false
|| 양쪽 데이터 중 한 개 이상이 true면 true, 둘다 false면 false
private static void 논리연산자() {
    boolean var1 = true;
    boolean var2 = true;
    boolean var3 = false;
    boolean var4 = false;

    System.out.println("var1 && var2");
    System.out.println(var1 && var2);
    System.out.println("var1 && var3");
    System.out.println(var1 && var3);
    System.out.println("var1 || var3");
    System.out.println(var1 || var3);
    System.out.println("var3 || var4");
    System.out.println(var3 || var4);
}

&& 연산자는 첫번째 데이터가 false라면 두번째 데이터는 확인하지 않습니다.

|| 연산자는 첫번째 데이터가 true라면 두번째 데이터는 확인하지 않습니다.

 

instanceof

instanceof는 왼쪽 데이터가 오른쪽 클래스와 일치하면 true입니다.

public class Test1 extends TestParent {
}

public class TestInterfaceImpl implements TestInterface {
}

private static void instanceofTest() {
    Test1 test1 = new Test1();  // TestParent를 상속 받은 클래스
    TestInterfaceImpl testInterfaceImpl = new TestInterfaceImpl();  // TestInterface를 implements 받은 클래스

    System.out.println("test1 instanceof Test1");
    System.out.println(test1 instanceof Test1);
    System.out.println("test1 instanceof TestParent");
    System.out.println(test1 instanceof TestParent);
    System.out.println("testInterfaceImpl instanceof TestInterfaceImpl");
    System.out.println(testInterfaceImpl instanceof TestInterfaceImpl);
    System.out.println("TestInterfaceImpl instanceof TestInterface");
    System.out.println(testInterfaceImpl instanceof TestInterface);
}

instanceof는 상속을 받은 클래스와 상속을 한 클래스도 true가 됩니다.

마찬가지로 interface와 implements 받은 클래스도 결과는 true가 됩니다.

 

assignment(=) operator

오른쪽의 피연산자 값을 왼쪽 피연산자에 할당합니다.

= 는 다른 연산자와 같이 쓸 수 있습니다.

private static void assignmentTest() {
    int a = 8;
    int b = 3;

    System.out.println("a = b -> " + (a = b));      
    System.out.println("a += b -> " + (a += b));    // a = a + b
    System.out.println("a -= b -> " + (a -= b));    // a = a - b
    System.out.println("a *= b -> " + (a *= b));    // a = a * b
    System.out.println("a /= b -> " + (a /= b));    // a = a / b
    System.out.println("a %= b -> " + (a &= b));    // a = a & b
}

 

화살표 (->) 연산자

화살표 연산자는 Lamda가 나타나고 생긴 연산자 입니다. ( Java 8 시점 ) 

람다 표현식은 단일 메서드 인터페이스인 경우  간결하게 표현할 수 있는 방식입니다.

화살표 연산자 왼쪽에는 파라미터를 작성하고 오른쪽에는 파라미터로 수행할 로직을 블록을 설정하여 작성합니다. 만약 로직이 한 줄이라면 블록은 생략할 수 있습니다.

private static void lamdaTest() {
    Test1 test1 = new Test1();
    test1.addTestInterface(new TestInterface() {
        @Override
        public void addTestListener(Object o) {
            System.out.println("add Test lister = " + o);
        }
    });
    test1.callInterface("not use lamda");


    Test1 test2 = new Test1();
    test2.addTestInterface(testLister -> {
        System.out.println("add Test lister lamda = " + testLister);
    });
    test2.callInterface("use lamda");
}

코드의 2가지 로직은 같은 기능을 수행합니다.

이처럼 람다표현식을 사용하면 소스를 간결화할 수 있습니다.

 

3항 연산자

자바에서는 3개의 연산자를 이용하는 조건 연산자입니다.

물음표와 콜론을 사용하는 연산자입니다.

private static void 삼항연산자() {
    String a = "a";

    System.out.println("a == a -> " + (a == "a" ? true : false));    // 1)
    System.out.println("a == b -> " + (a == "b" ? true : false));
    
    
    // 1) 과 동일하게 작동
    if (a == "a") {
        return ture;
    } else {
        return false;
    }
}

{조건} ? {조건이 참인 경우 실행} : {조건이 거짓인 경우 실행}

3개의 피연산자인 경우에만 사용하는 것을 추천합니다.

아래 코드는 3항 연산자를 두 번 사용한 코드입니다. 과연 보기 편한가요???

boolean c = a == "b" ? a == "c" ? false : true : false;

 

연산자 우선 순위

https://androiddeveloper.tistory.com/59

저 같은 경우는 모든 것을 암기하지 않고 꼭 먼저 실행되어야 하는 연산은 괄호를 붙혀서 사용하고 있습니다. 

 

java13 switch 연산자

일반적으로 사용하는 switch 문과 java12부터 추가된 multi, java13부터 추가된 arrow를 살펴보겠습니다.

private static void switchTest(String a) {
    // basic switch
    switch (a) {
        case "a" :
            System.out.println("a");
            break;
        case "b" :
            System.out.println("b");
            break;
        case "c":
            System.out.println("c");
            break;
        default:
            System.out.println("default");
    }

    // multi switch
    switch (a) {
        case "a", "b":
            System.out.println("a or b");
            break;
        case "c", "d":
            System.out.println("c or d");
            break;
        default:
            System.out.println("default");
    }

    // arrow switch
    switch (a) {
        case "a" -> System.out.println("a");
        case "b" -> System.out.println("b");
        case "c" -> System.out.println("c");
        default:
            System.out.println("defalut");
    }

    // expression
    String result = switch (a) {
        case "a" -> "TextA";
        case "b" -> "TextB";
        case "c" -> "TextC";
        default -> "default";
    }
}

위와 같이 switch 문을 사용할 수 있습니다.

 

 

 

 

 

반응형