본문 바로가기

개인적으로 공부한 것을 정리해 놓은 블로그입니다 틀린 것이 있으면 댓글 부탁 드립니다!


JAVA

JAVA 스터디 3 - 연산자

반응형

목표

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

학습할 것

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

1.산술 연산자

  +   -   *   /   %    

 

사칙연산을 다루는 연산자로 , 가장 기본적이면서 가장 많이 사용되는 연산자 중 하나이다 . 산술 연산자는 모두 두 개의 피연산자를 가지는 이항 연산자이며 , 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다. 

 항이란 해당 연산의 실행이 가능하기 위해 필요한 값이나 변수를 의미하며 이항 연산자란 해당 연산의 실행을 위해서 두개의 값이나 변수가 필요한 연산자를 의미한다 .

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Test1 {
    public static void main(String[] args) {
        int a = 10 ;
        int b = 5;
        int result;
 
        // +
        result = a + b ; // 15
 
        // -
 
        result = a - b ; // 5
 
        // *
 
        result = a * b ; // 50
 
        // %
 
        result = a % b ; //0
    }
}
cs

2.비트 연산자

 연산이 되는 값들을 내부적으로 비트단위로 변경한 후 연산을 수행한다 .(10진수를 2진수로 바꿈)

정수 타입만 비트연산이 가능하고 , 실수형태는 연산이 불가능하다

 

& 비트 단위의 AND

| 비트 단위의 OR

^ 비트 단위의 XOR

~ 비트 반전(0은 1로 1은 0으로 바뀜)

 

& 비트 단위의 AND

 

0    0     ->    0

1    0     ->    0

0    1     ->    0 

1    1     ->    1

&는 위의 방식으로 연산된다  둘다 같아야 1이 된다

 

ex) int a = 12 ;
    int b = 20 ;

int result = a&b;   <- result는 4가 담긴다 (비트단위로 연산후 10진수로 변환하여 값을 리턴한다.)

위의 a&b는 아래와 같이 동작한다 .

                                         
00000000 00000000 00000000   00001100  <-  12
                                 
                               &
                                         
00000000 00000000 00000000   00010100  <-  20 
                               =
00000000 00000000 00000000   00000100  <-  4

 

| 비트 단위의 OR

 

0    0     ->    0

1    0     ->    1

0    1     ->    1 

1    1     ->    1

OR는 위의 방식으로 연산된다 둘 중 하나라도  1이면 1이된다.

 

ex) int a = 12 ;

    int b = 20 ;


int result = a|b;   <- result는 4가 담긴다 (비트단위로 연산후 10진수로 변환하여 값을 리턴한다.)


위의 a&b는 아래와 같이 동작한다 .
                                     
00000000 00000000 00000000   00001100  <-  12                                 
                               &
00000000 00000000 00000000   00010100  <-  20 
                               =
00000000 00000000 00000000   00011100  <-  28

^ 비트 단위의 XOR

0    0     ->    0

1    0     ->    1

0    1     ->    1 

1    1     ->    1

서로 반대여야만 1이 된다 서로같으면 0이된다

 

ex) int a = 12 ;

    int b = 20 ;


int result = a^b;   <- result는 4가 담긴다 (비트단위로 연산후 10진수로 변환하여 값을 리턴한다.)


위의 a&b는 아래와 같이 동작한다 .
                                     
00000000 00000000 00000000   00001100  <-  12                                 
                               ^
00000000 00000000 00000000   00010100  <-  20 
                               =
00000000 00000000 00000000   00011100  <-  28

 

 ~ 틸트 연산자 ( 값을 반전시킴)

ex) int a = 12 ;

    int b = 20 ;


int result = ~a;   


위의 ~a는 아래와 같이 동작한다 .
                                     
00000000 00000000 00000000   00001100  <-  12                                 
                               ~
                               =
11111111 1111111111111111  11110011  <-  -13
  

 

 

비트 이동 연산자 (<< , >> ,>>>)

 

- 비트 단위의 연산처리를 하며 자료의 가공을 위해 bit 값을 오른쪽 또는 왼쪽으로 이동하여 값에 대한 변화를 일으키는 연산자 

 

1. x<<y : 정수 x의 비트를 y만큼 왼쪽으로 이동시킨다. (빈자리는 0으로 채워짐)

2. x>>y : 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킨다 (빈자리는 정수의 최상위 부호비트와 같은 값으로 채워진다. )

3. x>>>y: 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킨다 . (빈자리는 0으로 채워진다.)

 

예시)
2  << 3
00000000 00000000 00000000 00000010  <- 2 
2 << 3는 아래와 같이 2를 32비트로 분해한 다음 왼쪽으로 3비트 이동시킨다
00000000000 00000000 00000000 00000010???
3비트가 왼쪽으로 이동 되었고 오른쪽 맨 끝 3자리가 비어졌다 . 이때 ???의 빈자리는 아래와 같이 0으로 채워진다.
00000000 00000000 00000000 00010000 <- 16
결과적으로 2진수로 표현된 2를 16으로 바뀌었다.


16>>3
00000000 00000000 00000000 00001000 <- 16
00000000 00000000 00000000 00000001000 
이번에는 오른쪽으로 3비트가 이동되어서 오른쪽의 000이 아래와 같이 사라진다.
00000000 00000000 00000000 00000001 <-  2
위의 예시와 반대로 2진수로 표현된 16를 2으로 바뀌었다.

 

부호비트와 Int의 범위

 

int 값의 범위는 2진법으로 -2^31 ~2^31-1 이다 .

int 는 4byte 즉 32 비트를 사용한다. 32개의 bit 공간을 1로 채운다면 값은 10진수로 4,284,867,295가 된다.

하지만 위와 같이 사용할 경우 음수표현을 할 수없기 때문에 맨앞 자리를 부호로 사용하며 이를 부호비트라한다

 

0== 양수

1== 음수

 

3.관계 연산자 

 

비교 연산자라고도 하며 수학에서의 부등호를 생각하면 된다. 관계연산자의 결과는 true 혹은 false 값인 boolean 타입으로 반환 된다. 제어문에서 많이 사용되는 연산자 이다.

연산자 기능 연산 예제
> 왼쪽 항이 크면 참을, 아니면 거짓을 반환 3 >4  true
< 왼쪽 항이 작으면 참을 아니면 거짓을 반환 3<4   true
>= 왼쪽 항이 오른쪽 항 보다 크거나 같으면 참, 아니면 거짓  3 >= 4  false
<= 왼쪽 항이 오른쪽 항 보다 작거나 같으면 참 , 아니면 거짓 3 <= 4 true
== 두 개 항의 값이 같으면 참, 아니면 거짓을 반환 3 == 4 false
!= 두 개 항이 다르면 참, 아니면 거짓을 반환 3 != 4 false

 

4.논리 연산자

논리 연산자는 AND(&&) , OR(||) , NOT(!) 세가지의 연산자가 있으며 관계연산자와 같이 사용 되는 경우가 많다 .논리 연산자 역시 연산의 결과가 true 혹은 false로 반환 된다

 

연산자 기능 연산 예제
&& 두 항이 모두 참인 경우에만 결과 값이 참이다 .그렇지 않으면 거짓을 반환한다. true&&true = true
|| 두 항 중 하난의 항만 참이면 결과 값은 참이다. 두항이 모두 거짓이면 결과 값은 거짓이다. true || false = true
! 단항 연산자이다. 참인 경우는 거짓으로 바꾸고 , 거짓인 경우는 참으로 바꾼다. !true = false 

* 단락회로평가(short circuit evaluation)

 단락회로 평가는 논리 연산자를 사용할 때 고려해야 할 사항으로 두항 중  핲의 항에서 결과 값이 정해지는 경우 뒤의 값이 참인지 거짓인지 평가하지 않는 것을 말한다.

ex) int a = 10 ;

     int b =3;

     

     boolean c = ( ( a = a + 10 ) < 10 ) && ( ( b = b+2 ) <10 ) 

     

   위의 연산 과정에서 단락회로평가가 이뤄지며 &&연산에서는 둘중 하나라도 false면 false 이고 , 첫번째 항에서 false 가 나왔기 떄문에 뒤의 연산은 따로하지 않는다 .

   

    boolean d = ( ( a = a + 10 ) < 10 ) | | ( ( b = b+2 ) <10 ) 

 

 위의 연산은 OR 연산이기 때문에 둘중 하나면 true여도 true가 나온다  이럴 경우에는 앞에서 false가 나와도 뒤의 값이 true가 나올 수 있기 때문에 단락회로 평가가 일어나지 않는다. 

5.Instance of 연산자

 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아 보기 위해 instanceof 연산자를 사용한다. 주로 조건문에 사용되고  instanceof의 왼쪽에는 참조변수를 오른쪽에는 타입(클래스명) 이 피연산자로 위치한다. 그리고 연산의 결과로 boolean 값인 true , false 중의 하나를 반환한다 .

instancof를 이용하여 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다 

Test1 클래스
Test2 클래스
Test3 클래스

 

위의 그림을 예시로 intanceof 를 설명하면 

Test2 는 Test1을 Test3는 Test2를 상속받고 있다.

Test 1의 메인메서드 안에서 Test1,Test2,Test3를 Test1의 메인메서드에서 생성한 후 

instanceof로 검증해보면

test2 ,test3 두 변수 모두 Test1을 상속받기 때문에 true가 반환되고 

아래와 같이 출력된다.

 

6. 대입연산자 (assignment(=) operator,할당연산자)

대입 연산자는 변수에 값을 대입할 때 사용하는 이항 연산자이며, 피연산자들의 결합 방향은 오른쪽에서 왼쪽이다 .

또한 , 자바에서는 대입 연산자와 다른 연산자를 결합하여 만든 다양한 복합 대입 연산자를 제공한다.

 

 연산자설명

= 왼쪽의 피연산자에 오른쪽의 피연산자를 대입함.
+= 왼쪽의 피연산자에 오른쪽의 피연산자를 더한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
-= 왼쪽의 피연산자에서 오른쪽의 피연산자를 뺀 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
*= 왼쪽의 피연산자에 오른쪽의 피연산자를 곱한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
/= 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
%= 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 나머지를 왼쪽의 피연산자에 대입함.
&= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 AND 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
|= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 OR 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
^= 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 XOR 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
<<=

왼쪽의 피연산자를 오른쪽의 피연산자만큼 왼쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.

>>= 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호를 유지하며 오른쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.
>>>= 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호에 상관없이 오른쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입함.

 

* www.tcpschool.com/java/java_operator_assignment 표 참조

 

  비트 연산자를 공부한 겸 한번 하나씩 해봤다. a 변수 선언한 것이 안나왔다 초깃값은 int a = 5 였다.

 

6.화살표(->) 연산자

  람다함수를 만들때 사용되는 표현식이다 .

 

람다함수

  2010년에 Project Lambda 라는 프로젝트로 진행되어 Java 8부터 공식 릴리즈 되었다 . 

자바에는 함수의 개념이 없었다  이런 이유로 기존의 자바 언어 체계에서는 함수형 언어를 언어 차원에서 지원하지는 못하였다 . 

 때문에 , Java8에서 함수형 인터페이스 ( 단 하나의 메소드만이 선언된 이터페이스) 라는 개념을 도입하게 되었고 ,함수형 인터페이스의 경우 , 람다식으로 표현이 가능할 수 있게 제공하였다 .

  Java8에서 함수형 인터페이스라는 개념과 람다 표현을 통해 입력에 의해서만 출려이 결정되도록 '순수한 함수' 를 표현할 수있게 되었고 , 람다식으로 표현함으로써 ' 익명함수 ' 를 정의할 수있게 되었다. 함수형 인터페이스의 메소드에서 또다른 함수형 인터페이스를 인자로 받을 수 잇도록 하여 '고계함수'를 정의할 수 있게 되었다 .즉, 함수형 프로그래밍 언어의 조건을 만족 시킬 수 있게 되었다 

 

자바에서의 기본적인 람다식 구조

( int a , int b ) -> { return a + b }

특징

 

1.단순한 람다 구문의 경우 , 람다 구분에 중괄호가 없을 수도 있다 .

2.return 이 없을 수 도 있다 .

3.매개변수에는 타입을 명시하지 않아도 된다 .(타입 추론)

4.람다식 문법을 컴파일러가 익명 클래스로 변환한다. 즉 , 함수형 인터페이스를 컴파일러가 구현하도록 위임하는 형태라 할 수 있다. 

 

람다 표현식 활용( 익명함수등 학습 후 다시 찾아보자.)

 

 파라미터에 행위전달(Parameterized Behaviors)

  메소드에 사용할 데이터 혹은 변수와 행위를 같이 전달하게 하여 메소드의 행위 부분도 분리할 수 있다. 

  -장점

   -런타임에 행위를 전달 받아서 제어 흐름 수행(전략 패턴)

   - 메소드 단위의 추상화가 가능

   - 함수형 언어의 고차함수(Higher-Order Function)

 

불변 변수 사용 (Imumutable Free Variables)

 자바에서 익명클래스 +자유 변수 포획으로 클러저를 가능하게 했는데 , 포획된 변수에서는 명시적으로 final 지시자를 사용하게 하였다. 람다식에서는 포획된 변수에 명시적으로 final 을 명시하지 않아도 포획된 변수는 변경할 수 없고 , 변경하는 경우 컴파일 에러가 발생한다.

변수의 변경이 불가능하다 

 

Optional + Lamda 조합

 java.util.Optional 이라는 클래스는 값이 있거나 없는 경우를 표현하기 위한 클래스로 map,filter ,flatMap 등의 고차 함수를 가지고 있다. Optional의 고차 함수를 조합하여 간결하게 표현이 가능하며 , 언제발생할지 모르는 NullPointerException으로 부터 자유롭다.

 

8. 3항 연산자

if else 구문을 표현하는 연산자 .

 

ex)
int a;

if(5<4) {
   a=50   
}else{
   a=40
}

위의 if else  문을 삼항연산자로 표현하면 아래와 같다

int a =( 5<4 ) ? 50 : 40 ;

 

조건문? 참일 경우 리턴값 : 거짓일 경우 리턴값;

위와 같은 문법으로 구현된다.

 

코드라인 수를 줄일 수 있기 때문에 가벼운 로직을 처리한다면 삼항연산자로 처리하는 것이 좋다 .

 

주의 할 점은 삼항연산자를 사용하여 코드 라인이 줄어든다고 컴파일 속도가 빨라지는 것은 아니며

삼항연산자를 중복 사용할시 가독성이 떨어질 수 있으므로 중복처리는 피하는 것이 좋다.

 

9.연산자의 우선순위 ( operator precedence )와 결합 방향 (associativity)

 

 연산자의 우선순위는 수식 내에 여러 연산자가 함께 등장할 때 , 어느 연산자가 먼저 처리될 것인가를 결정한다 .

           

        우선순위                                 연산자                              설명                              결합 방향

1 [] 첨자 연산자 왼쪽에서 오른쪽으로
  . 멤버 연산자 왼쪽에서 오른쪽으로
2 ++ 후위 증가 연산자 왼쪽에서 오른쪽으로
  -- 후위 감소 연산자 왼쪽에서 오른쪽으로
3 ! 논리 NOT 연산자 오른쪽에서 왼쪽으로
  ~ 비트 NOT 연산자 오른쪽에서 왼쪽으로
  + 양의 부호 (단항 연산자) 오른쪽에서 왼쪽으로
  - 음의 부호 (단항 연산자) 오른쪽에서 왼쪽으로
  ++ 전위 증가 연산자 오른쪽에서 왼쪽으로
  -- 전위 감소 연산자 오른쪽에서 왼쪽으로
  (타입) 타입 캐스트 연산자 오른쪽에서 왼쪽으로
4 * 곱셈 연산자 왼쪽에서 오른쪽으로
  / 나눗셈 연산자 왼쪽에서 오른쪽으로
  % 나머지 연산자 왼쪽에서 오른쪽으로
5 + 덧셈 연산자 (이항 연산자) 왼쪽에서 오른쪽으로
  - 뺄셈 연산자 (이항 연산자) 왼쪽에서 오른쪽으로
6 << 비트 왼쪽 시프트 연산자 왼쪽에서 오른쪽으로
  >> 부호 비트를 확장하면서 비트 오른쪽 시프트 왼쪽에서 오른쪽으로
  >>> 부호 비트까지 모두 비트 오른쪽 시프트 왼쪽에서 오른쪽으로
7 < 관계 연산자(보다 작은) 왼쪽에서 오른쪽으로
  <= 관계 연산자(보다 작거나 같은) 왼쪽에서 오른쪽으로
  > 관계 연산자(보다 큰) 왼쪽에서 오른쪽으로
  >= 관계 연산자(보다 크거나 같은) 왼쪽에서 오른쪽으로
  instanceof 인스턴스의 실제 타입 반환 왼쪽에서 오른쪽으로
8 == 관계 연산자(와 같은) 왼쪽에서 오른쪽으로
  != 관계 연산자(와 같지 않은) 왼쪽에서 오른쪽으로
9 & 비트 AND 연산자 왼쪽에서 오른쪽으로
10 ^ 비트 XOR 연산자 왼쪽에서 오른쪽으로
11 | 비트 OR 연산자 왼쪽에서 오른쪽으로
12 && 논리 AND 연산자 왼쪽에서 오른쪽으로
13 || 논리 OR 연산자 왼쪽에서 오른쪽으로
14 ? : 삼항 조건 연산자 오른쪽에서 왼쪽으로
15 =

대입 연산자 및 복합 대입 연산자

(=, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, ^=, |=)

오른쪽에서 왼쪽으로

 *tcpschool.com/java/java_operator_arithmetic 에서 표 참조 

 

10. switch 연산자  (Java 13) (스위치문 공부 후에 다시 조사)

 

 

참조 

coding-factory.tistory.com/266 (3항연산자)

 

반응형