JAVA STUDY(with whiteship) 3주차

hwk·2020년 11월 28일
0

JAVA STUDY

목록 보기
2/12

연산자

목표

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

목차

  1. 산술 연산자
  2. 비트 연산자
  3. 관계 연산자
  4. 논리 연산자
  5. instanceof
  6. assignment(=) operator
  7. 화살표(->) 연산자
  8. 3항 연산자
  9. 연산자 우선 순위
  10. (optional) Java 13. switch 연산자

1. 산술 연산자

  • 산술 연산자의 요소 : +, -, , /, %
    (+) : 두 피연산자의 값을 덧셈
    (-) : 왼쪽 피연산자 값에서 오른쪽 피연산자 값을 뺄셈
    (
    ) : 두 피연산자의 값을 곱셈
    (/) : 왼쪽 피연산자 값을 오른쪽 피연산자 값으로 나눴을 때의 몫 반환
    (%) : 왼쪽 피연산자 값을 오른쪽 피연산자 값으로 나눴을 때의 나머지 반환
  • 산술 연산자의 계산 순서는 수학 계산식 우선순위를 따른다.
  • 변수 선언문에 연산식 사용 가능
int result = n1 + n2;
  • 정수형 나눗셈과 실수형 나눗셈
1) System.out.println("정수형 나눗셈 : " + 7/3);
2) System.out.println("실수형 나눗셈 : " + 7.0f/3.0f);
3) System.out.println("실수형 나눗셈 : " + (float)7/3);

1의 경우 두 피연산자가 정수일 때 나머지는 버려지고 몫인 2가 출력된다.
2의 경우 두 피연산자가 실수일 때 실수형 나눗셈이 적용되어 나머지 없이 '2.3333333'이 출력된다.
3의 경우는 실수형과 정수형의 나눗셈인데, 정수형이 실수형으로 자동 형 변환 되어 2와 같이 실수형 나눗셈이 적용된다.

  • 복합 대입 연산자
    대입 연산자와 복합 연산자가 합해져서 만들어진 복합 대입 연산자는 다음과 같이 표기할 수 있다.
    a = a + b → a += b
    a = a - b → a -= b
    a = a b → a = b
    a = a / b → a /= b
    a = a % b → a %= b

2. 비트 연산자


(출처 : https://heurinbada.tistory.com/20)

n1 & n2 // n1과 n2를 비트 단위로 AND 연산
n1 | n2 // n1과 n2를 비트 단위로 OR 연산
n1 & n2 // n1과 n2를 비트 단위로 XOR 연산
~n // n의 모든 비트를 반전시켜서 얻은 결과를 반환
  • 비트 연산자는 비트 단위로 진행된 연산의 결과를 묶어서 하나의 연산 결과를 반환한다.
    ex)
int n1 = 13;
int n2 = 7;
int n3 = n1 & n2;

위와 같이 동일한 위치에 있는 비트별로 연산하고, 그 결과를 하나의 정수로 반환한다.

  • 피연산자는 반드시 정수이어야 한다.

  • 언뜻 하트웨어 컨트롤을 떠올리기 쉽지만 일반적으로 응용 프로그램 개발에서도 매우 유용하게 사용된다.

  • 비트 쉬프트 연산자

    (출처 : https://unknownyun.blogspot.com/2018/08/blog-post_59.html)
    - '>>'와 '>>>'의 차이점은 양수, 음수를 판단하는지의 여부이다.
    - 왼쪽으로 비트 열을 n칸 이동시키면 2의 n제곱을 곱하고 오른쪽으로 이동시키면 2의 제곱 나눗셈 하는 결과가 된다.
    - 비트를 이동시키는 연산은 곱셈과 나눗셈 보다 CPU에게 있어서 부담이 되지 않는다.
    성능을 생각한다면 2의 배수 단위로 값을 증감할 때는 비트 연산자를 사용해 보도록 하자.
    이 밖에도 비트 연산자의 활용 범위는 한정 지을 수 없을 만큼 다양하게 활용되고 있다고 한다.
    그 활용에 대해서는 아래 링크를 달아 두겠다.
    https://shoark7.github.io/programming/knowledge/some-useful-bit-tricks-and-usages

3. 관계 연산자

  • '<, >, <=, >=, ==, !=' 으로 구성되어 있고 true 혹은 false를 반환한다.
n1 < n2 // n1이 n2보다 작은가?
n1 > n2 // n1이 n2보다 큰가?
n1 <= n2 // n1이 n2보다 작거나 같은가?
n1 >= n2 // n1이 n2보다 크거나 같은가?
n1 == n2 // n1이 n2보다 같은가?
n1 != n2 // n1이 n2보다 다른가?

4. 논리 연산자

  • 논리 연산자 역시 true 혹은 false를 반환하는 연산자로써 AND(논리곱), OR(논리합), NOT(논리부정)을 의미하는 연산자로 구성되어 있다.
A && B // A와 B 모두 true이면 연산결과는 true (논리 AND)
A || B // A와 B 둘 중 하나라도 true이면 연산결과는 true(논리 OR)
!A // 연산결과는 A가 true이면 false, A가 false이면 true(논리 NOT)

이 연산에 대한 진리 표는 아래와 같다.

(출처 : https://m.blog.naver.com/PostView.nhn?blogId=brickbot&logNo=220508046954&proxyReferer=https:%2F%2Fwww.google.com%2F)

  • 논리 연산자와 (Short-Circuit Evaluation(Lazy Evaluation)
    자바 연상자의 연산특성 중 하나로써, "가장 빠르게 연산을 진행하기 위한 계산 방식"이 있다.
    '&&'연산자의 왼편의 피연산자가 false이면, 오른편에 있는 피연산자에 상관없이 연산결과는 false가 된다.
    그렇기 때문에 자바는 이러한 상황에서 && 연산자의 오른편을 실행하지 않는다.
    마찬가지로 || 연산자의 왼편에 있는 피연산자가 true이면, 오른편에 있는 피연산자에 상관 없이 || 연산의 결과는 true가 되므로 오른편은 실행하지 않는다.
    예시는 아래와 같다.
class SCE
{
	public static void main(String[] args)
    {
    	int num1, num2 = 0;
        boolean result;
        
        result = (num1+=777)<0 && (num2+=777)>0;
        // num1은 777이고 num2는 0
        
        result = (num1+=777)>0 && (num2+=777)>0;
        // num1은 777+777이고, num2는 0
    }
}

그러므로 논리 연산자를 사용할 때는 복잡한 로직의 피연산자는 오른편에 두고 간단한 로직의 피연산자는 왼편에 둠으로써 연산의 성능 향상을 시키자.

5. instanceof

  • 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아볼 때 instanceof 연산자를 사용한다.
    true 혹은 false를 반환.
  • "객체 instanceof 클래스" 형식으로 사용한다.
  • 주로 상속관계를 확인할 때 사용한다.
public class InstanceofExam {
	public static void main(String[] args) {
		
		A a = new A();
		B b = new B();
		
		
		//객체 a는 자기 자신의 객체이기 때문에 형변환 가능.
		System.out.println(a instanceof A);  //true 출력
		
		//객체 b는 A의 자식객체이기 때문에 A로 형변환 가능.
		System.out.println(b instanceof A);  //true 출력
		
		
		//객체 a는 B의 부모객체이기때문에 형변환 불가능.
		System.out.println(a instanceof B);  //false 출력
		
		//객체 b는 자기 자신의 객체이기때문에 형변환 가능.
		System.out.println(b instanceof B);  //true 출력
		
	} 
}


class A{
	
}

class B extends A{
	
}

부모객체가 자식객체 타입의 형변환이 불가능한데,
이는 자식 클래스의 요소들이 부모 클래스의 요소를 포함하고 있기 때문이다.
즉 부모객체가 자식객체타입으로 형변환을 하려는 것은
좁은 범위가 넓은 범위를 커버하려는 것과 같다.

6. assignment(=) operator

  • A=B
    우변의 값을 좌변의 변수에 할당한다.
  • 복합 대입 연산자
    위 "#1. 산술 연산자" 에서 자세하게 다루었고 아래와 같은 복합 대입 연산자가 있다.
    "-=, /=, %=, &=, |=, ^=, >>=, >>>=, <<="

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

  • 람다식에서 사용한다.
    (람다식이란 "식별자없이 실행가능한 함수".
    함수를 따로 선언하지 않고 코드한줄에 함수를 써서 그것을 호출하는 방식이다.)
    java 8 부터 추가된 기능으로 익명객체를 생성하기 위한 표현식을 말한다.
  • (매개변수, ...) -> { 실행문 ... }
    - (매개변수, ...)는 오른쪽 중괄호 { } 블록을 실행할 때 쓰는 값을 제공하는 역할을 한다.
    - 매개 변수의 이름은 자유롭게 지정할 수 있으며 인자타입도 명시하지 않아도 된다.
    - 매개변수가 하나일 경우 매개변수를 생략 할 수 있다.
    ( ) -> {함수몸체}
    - 화살표 기호(->)는 매개 변수를 이용해서 중괄호 { } 바디를 실행한다는 뜻.
    (매개변수) -> {함수몸체}
    - 함수몸체가 단일 실행문이면 괄호{}를 생략 할 수 있다.
    (매개변수) -> 함수몸체
    • 함수몸체가 return문으로만 구성되어 있는 경우 괄호{}를 생략 할 수 없음.
      (매개변수) -> {return 0;}
  • ex
 Runnable runnable = new Runnable(){ public void run(){ ... } } // 람다식 사용 x
 
 
 Runnable runnable = () -> { ... } // 람다식 사용 o

함수 정의 형태를 띠고 있지만 런타임 시에 인터페이스의 익명 구현 객체로 생성된다. 위의 코드는 Runnable 변수에 대입되므로 람다식은 Runnable의 익명 구현 객체를 생성하게 된다

  • 람다식의 장단점

장점

  1. 코드를 간결하게 만들 수 있다. 코드의 의도가 명확히 드러나기때문에 가독성 향상.

  2. 함수를 만드는 과정없이 한번에 처리할 수 있기에 코딩하는 시간이 줄어든다.

  3. 병렬프로그래밍에 용이.

단점

  1. 람다를 사용하면서 만드는 무명함수는 재사용이 불가능.
    이로 인해 비슷한 함수를 계속 중복생성할 가능성이 높아서
    잘못 쓰면 전체적으로 코드가 지저분해질 수 있다.

  2. 디버깅이 다소 까다롭다

  3. 재귀로 만들경우에는 다소 부적합한면이 있다.

8. 3항 연산자

변수 = (조건문) ? (참일 때 반환 값) : (거짓일 때 반환 값);

  • ex)
int a = (5<4) ? 10 : 20;

9. 연산자 우선 순위

  • 동일한 연산자가 하나의 연산식 안에 둘 이상 놓여있을 때, 연산의 순서를 결정짓는 요소가 '연산방향'이다.


(출처 : https://noritersand.github.io/java/java-%EC%97%B0%EC%82%B0%EC%9E%90-operator/)

10. (optional) Java 13. switch 연산자

  • 기존
 int jdkClassic(int input) {
        int result = 0;
        switch(input){
            case 1:
            case 2:
                result = 1;
                break;
            case 3:
            case 4:
                result = 2;
                break;
            default:
                result = 3;
                break;
        }
        return result;
    }

result를 변수를 만들어야 하고 multiple case를 지원하지 않는다.

  • 자바 13
 int jdk13(int input) {
        return switch (input) {
            case 1, 2:
                yield 1;
            case 3, 4:
                yield 2;
            default:
                yield 3;
        };
    }
  1. 문장이 아닌 식으로 가능. 그로 인해서 return 값으로 사용 가능
  2. multiple case를 지원
  3. yield와 같은 키워드를 통해 값을 리턴 가능.

참고 서적 : 난 정말 JAVA를 공부한 적이 없어요 (ORANGE MEDIA 윤성우 저)

profile
Elegant Dev

0개의 댓글