책읽기

[Java의 정석][Chapter-3] 연산자

pythaac 2021. 8. 4. 11:33
이 글은 "Java의 정석 (남궁 성 지음)"을 읽고 주관적으로 요약한 글입니다. 

출처 : http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788994492032#N

 

1. 연산자

  • 연산자와 피연산자
    • 연산자
      - 연산을 수행하는 기호
    • 피연산자
      - 연산자의 작업 대상
  • 대입 연산자(=)
    • 식(expression)
      - 연산자와 피연산자를 조합하여 계산하고자하는 바를 표현하는 것
    • 식을 평가?(evaluation)
      - 식을 계산하여 결과를 얻는 것
  • 연산자 종류
    • 산술 연산자
      - [ + - * / % << >> ]
    • 비교 연산자
      - [ > < >= <= == != ]
    • 논리 연산자
      - [ && || ! & | ^ ~ ]
    • 대입 연산자
      - [ = ]
    • 기타
      - [ (type) :? instanceof ]
    • 우선순위
      - 산술 > 비교 > 논리 > 대입
      - 단항 > 이항 > 삼항
      - 같은 종류의 연산자들은 우선순위가 비슷함
  • 연산자의 결합규칙
    • 같은 우선순위의 연산자들이 여러 개일 경우 갖는 처리 규칙
    • 대부분
      - 왼쪽 -> 오른쪽
    • 단항 연산자, 대입 연산자
      - 오른쪽 -> 왼쪽
      - x = y = 3
    • [ * / ] > [ + - ]
    • [ && & ] > [ || | ]
  • 산술 변환
    • 피연산자 타입의 일치를 위한 자동 형변환
    • 쉬프트 연산자(<<, >>)와 증감 연산자(++, --) 예외
    • 산술 변환 규칙
      - 피연산자중 큰 타입으로 일치
      - float + int -> float + float
      - 피연산자 타입이 int보다 작으면 int로 변환

 

2. 단항 연산자

  • 증감 연산자(++ --), 부호 연산자(+ -)
  • 일반 산술 변환에 의한 자동 형변환이 일어나지 않음
  • 전위형(++a), 후위형(a++)
    • 값의 참조 전후
  • 예제
x = 1;
System.out.println(x++ - ++x); // -2
/* 
   1. x++는 참조되기 전까지 1 유지
   2. ++x에서 참조되면서 +1, 전위형으로 인한 +1로 3
   3. 1 - 3 = -2
*/
System.out.println(x); // 3

x = 1;
System.out.println(++x - x++); // 0
/* 
   1. ++x에서 2
   2. x++에서 참조되기 전까지 2 유지
   3. 2 - 2 = 0
*/
System.out.println(x); // 2

 

3. 산술 연산자

  • 10 / 4 -> 2
    • (int) / (int) -> (int)
    • 소수점 이하는 버려짐
  • long x = 1_000_000 * 2_000_000
    • x = -1454759936
    • 리터럴은 기본 int
    • long에 담기 전에 int형의 계산이었으므로, int 결과
    • int값을 long에 담으면 int의 값 그대로 들어감
  • char c = 'a';
    a++;
    • System.out.println(a)
      - 'b'
    • 단항 연산자 (++)은 형변환이 없음
    • 유니코드를 저장하는 char에 1을 추가
  • char c1 = 'a';
    (1) char c2 = c1 + 1; // 컴파일 에러
    (2) char c2 = 'a' + 1; // 정상 실행
    • (1)은 r-value가 int형이므로, char에 int를 담을 수 없음
    • (2)는 리터럴이라 컴파일 시 계산하므로 문제가 없다고 함
  • 유니코드 값은 대문자(A)가 소문자(a)보다 작음
  • 반올림 하는 법
    • 나누기(/)는 버림이므로 반올림할 수 없음
    • 0.5를 더한 int를 나누면 반올림됨
      - (int)(target+0.5) / 100.0
    • Math.round() 사용

 

4. 비교 연산자

  • 형변환
    • 10 == 10.0f
      - 10이 float로 변환되면서 값이 같아짐
      - true
    • 0.1 == 0.1f
      - float가 double로 바뀌면서 오차 발생
      - false
      - double형을 float로 변환하기
  • 문자열 비교
    • ==를 사용하면 객체 비교
    • equals() 메서드 사용하여 비교
    • eqaulsIgnoreCase()로 대소문자 구분 없이 비교

 

5. 논리 연산자

  • 효율적인 연산 (short circuit evaluation)
    • OR 연산
      - 한쪽만 true면 더 평가하지 않음
    • AND 연산
      - 한쪽만 false면 더 평가하지 않음
  • 비트 연산자
    • & | ^
    • XOR연산자는 두 비트가 다르면 1
  • 비트 전환 연산자(~)
    • 1의 보수를 구함
    • 음의 정수를 얻으려면 ~x+1
    • 양의 정수를 얻으려면 ~x-1
  • 쉬프트 연산자
    • >>의 경우
      - 부호 비트에 따라 해당 값을 빈 칸에 채움
    • x << n
      - x * 2n과 같음
    • 쉬프트 연산이 산술 연산자보다 빠르지만 가독성이 떨어짐

 

6. 그 외의 연산자

  • 조건 연산자
    • mod < 0.5 ? 0 : 0.5
      - 0과 0.5의 타입이 다르므로 형변환이 이뤄짐
      - 0 -> 0.0
  • 대입 연산자
    • 저장된 값을 연산 결과로 반환
      - System.out.println( x = 3 );
  • lvalue, rvalue
    • lvalue
      대입 연산자의 왼쪽 피연산자
    • rvalue
      대입 연산자의 오른쪽 피연산자