[CS] 자바의 정석 독서 #5 - 연산자

2025. 9. 22. 01:42·언어공부/Java | Kotlin

 

연산자는

산술연산 - 비교연산 - 논리연산 - 대입연산

순으로 우선순위를 가지며, 단항연산자의 우선순위가 이항연산자보다, 이항연산자가 삼항연산자보다 우선순위가 높다.

 

이 순서대로 연산 우선순위를 가지며, 산술연산 중에서 곱셈,나눗셈 - 덧셈,뺄셈 - 비트시프트 연산의 우선순위를 가진다.

이 밖에도 논리연산의 경우에는 &, && (AND)가 |, || (OR) 보다 우선순위가 높다. (&, |은 비트연산용) 괄호를 사용하여 우선순위를 명시적으로 표현하면 좋다.

 

또한 단항연산의 경우에는 오른쪽에서 왼쪽으로 (대표적인 예시가 -3 같은 부호단항연산), 대입 연산의 경우에도 오른쪽에서 왼쪽으로 (x = 4+5 면 4+5부터 계산) 진행되며 나머지 연산들은 모두 왼쪽에서 오른쪽으로 진행한다. C프에서 배운 내용들


산술연산과 산술변환

어제 캐스팅과 형변환 다룰 때 잠깐 나왔던 내용인데,

int i = 10;
float f = 20.0f;

float result = i + f;

이렇게 타입이 다른 두 변수를 더해야할 때, 하나하나 캐스팅으로 형변환을 하는 것이 아니라 컴파일러가 알아서 형변환을 해준다. 이를 산술변환이라고 칭한다.

 

산술변환 시에도 규칙이 있는데,

1. 형변환은 두 피연산자의 타입 중 byte - short/char - int - long - float - double 순서에서 저장할 수 있는 값이 더 큰 타입으로 두 피연산자의 타입이 일치된다. int 와 double을 더하면 두 피연산자와 결과값 모두 double로 통일

2. 피연산자의 타입이 int보다 작으면 int로 변환된다. 즉 byte나 short 를 더하면 모두 int로 형변환되어서 계산되고 결과도 int로 출력된다. 따라서 byte나 short는 별 필요가 없다. 약간 안좋게 말하자면 과거 바이트 수 하나하나가 중요했던 시기의 잔재정도?

 

y = m + n 등의 산술연산에서, y, m, n의 타입은 산술변환의 규칙에 맞춰서 하나로 통일된다. 만약 나눗셈에서 소수 결과를 얻고 싶다면 피연산자 중 하나를 float로 변환해야한다. 그렇지 않으면 정수 / 정수가 되어서 값도 소수점을 버린 정수로 출력된다. 반올림은 되지 않는데, 반올림을 원하면 Math.round() 메서드를 쓰거나 float 값에 0.5를 더해주면 된다,

 

산술연산자

산술변환 2번규칙 때문에 여러 오류가 터질 수 있는데, 대표적으로

byte a = 3;
byte b = 7;
byte c = a + c;

이러면 에러가 생긴다.

연산과정에서 a, c는 모두 int로 변환되고 덧셈한 값 역시 int로 반환되기에 c도 int로 선언되어야한다. 물론 캐스팅을 통해서 byte 값으로 구할 수는 있는데, int를 byte로 다시 형변환시키게 되는 것이므로 오버플로우가 일어날 수 있다.

int a = 1_000_000;
int c = 2_000_000;

long c = a * b;

마찬가지로 이러한 상황에서도 에러는 아니지만 오버플로우가 일어날 수 있는데, a*b는 int 값으로 값이 반환되므로 long 타입으로 변경해도 오버플로우된 int 값을 long으로 형변환하는거라 오버플로우가 그대로 유지된다. 수정하려면 a나 b를 연산과정에서 캐스팅을 통해 long으로 바꿔주어야한다.


char 타입도 내부에는 2바이트 정수로 저장되므로 산술연산을 적용할 수 있다.

'2' - '0' → 50 - 48 = 2로 똑같이 적용되며, 이는 유니코드값을 따른다.

 

따라서 산술연산의 규칙을 적용받는 연산으로, 위처럼 char + int나, char + char 형식으로 산술연산을 진행하면 각 피연산자가 int로 형변환되며, 계산결과도 int로 구해진다. 따라서 char c = c1 + 1; 이런 식으로 코드를 짜면 에러가 터진다. 캐스팅을 통한 형변환이 필요하다.

 

char c2 = 'a' + 1; //b

단 이런 방식으로는 에러가 터지지 않는데, 변수가 아닌 리터럴 간의 연산에서는 컴파일러가 알아서 형변환을 진행해주기 때문이다.


비교연산

연산결과는 오직 true와 false. 파이썬처럼 True, False가 아니니까 얼마나 편하고 좋아

 

비교는 간단하기 때문에 연산자도 많지 않다. < > <= >= == != 정도가 있고, 알아둘 것은 이항연산자이기 때문에 자동형변환의 적용대상이라는 것

 

10 == 10.0f;
'A' > 64;

모두 true다. 이는 산술연산에서 다뤘던 자동형변환의 과정과 일치한다..다만

 

0.1 == 0.1f //false

이렇게 소수연산에서는 오류가 생길 수 있는데, 그제 부동소수점에서 다뤘던 것처럼 0.1은 이진수로 변환하는 과정에서 오차가 발생하기 때문에 그렇다. 즉 이진소수의 대부분은 실제 값이 아니라 근사값을 저장한다고 볼 수 있겠다.

 

따라서 double과 float의 비교연산의 경우에는 무조건 double을 float로 바꿔서 진행해야한다. 그 반대의 경우에는 float에서 생긴오차가 그대로 double로 변환되기 때문이다. double을 float로 바꾸면 그 과정에서 오차가 발생하는데 어차피 발생하는 오차의 크기는 같으므로 == 연산자가 통하기 때문이다.

 

char은(는) != 이나 == 같은 비교연산이 가능했지만 String은 equals() 메서드를 사용해야한다. 내용이 같아도 다른 객체를 참조하고 있으면 == 연산에서 true가 반환되지 않기 때문이다. 대소문자 여부를 무시하고 싶다면 equalsIgnoreCase() 메서드


논리연산

AND -> && / OR -> ||

이외에는 AND, OR가 동일하다. AND -> true - true 일 때만 true / OR -> false - false 일 때만 false

다양한 예제는 p.136부터 참고

 

논리연산 역시 저번 컴공개 때 배웠던 것처럼, 효율적으로 연산을 진행한다.

OR 연산의 경우에는, 첫 번째 피연산자가 true면 무조건 true를 반환하고 두 번째 피연산자는 오류가 일어나던말던 통과한다

 

System.out.println( 1==1 || 1/0==1); //true
System.out.println( 1==3 || 1/0==1); //에러

이렇게

AND 연산에서는 첫 번째 피연산자가 false일 때 이러한 경우가 생긴다. 따라서 비교연산에서 좌항과 우항의 값을 잘 조절하면 연산속도를 줄일 수 있다.


비트연산

& | ^ ~ << >> 이 있다.

이진수가 비트에 저장되므로 (00000101과 00000011 이런 식으로..) 비트연산은 이런 비트 하나하나 논리연산을 실행한다.

 

즉 5 (이진수 00000101)와 3 (이진수 00000011) 에서

5 | 3 -> 00000111 (비트를 비교, 하나라도 1이면 1) -> 7

5 & 3 -> 00000001 (비트를 비교, 하나라도 0이면 0) -> 1

5 ^ 3 -> 00000110 (비트가 다를때만 1) -> 6

순서대로 OR, AND, XOR

 

이런 비트연산이 16진수 표현식에서 사용되는 경우가 있는데 이건 부동소수점처럼 따로 알아보려고 한다.. 16진수부터 배우고


조건연산 ?:

파이썬에는 if문 한 줄로 쓰기가 있는데

x = 0 if x > 0 else 1

자바에서 이에 대응하는 것이 조건연산자 ? : 이다.

조건식, 식1, 식2을 필요로하는 삼항연산자이며, (유일하다)

 

x = (x>0) 0 : 1 ;

이런식으로 위의 문장을 표시할 수 있다. 괄호의 조건식이 참일 경우에는 콜론의 왼쪽값이, 거짓일 경우에는 오른쪽값이 들어간다. 파이썬처럼 if-else 문으로 쓸 수 있으면 코드는 짧게 쓰는게 좋으니까

 

result = x > 0 ? 0 : (x==0 ? 0: -1);

근데 뭐든 적당히

콜론을 중심으로 좌우항은 산술변환이 발생한다. 0 : 0.5라면 0.0 : 0.5로 산술변환이 자동으로 일어난다. 연산결과 역시 double로 통일된다.


대입연산

제일 우선순위가 낮다. 대입연산자의 우항에는 식, 상수 등이 모두 가능하지만 좌항에는 반드시 값을 변경할 수 있어야한다. 좌항에 상수나 리터럴 같은 값이 들어오면 에러가 생긴다.

 

int i = 0;
i + 3 = 0;

이런 식으로

 

간혹 +=, *= 같은 복합대입연산자가 쓰이는데, 이는 대입연산자이 한 종류이기에 우선순위가 제일 낮다.

따라서 i *= 10 + 5; 라고하면 산술연산인 덧셈이 우선순위가 더 높기 때문에 i = i * (10+5); 가 계산된다.


연산자 부분은 이전에 해본적도 있고 내용도 아는 내용이라 빠르게빠르게 읽으며 넘어갔다.

 

다만 시간상 읽지 못한 단항연산자 부분과

2진수 - 16진수 변환과 비트연산과 16진수의 관계는 다른 글로 찾아보려한다. 우선 여기까지

'언어공부 > Java | Kotlin' 카테고리의 다른 글

[CS] 자바의 정석 독서 #6 - 클래스와 메서드  (0) 2025.09.24
[CS] 자바의 정석 독서 #6 - 객체지향 프로그래밍, OOP란 무엇인가?  (0) 2025.09.24
[CS] 자바의 정석 독서 #4 - 형변환  (0) 2025.09.21
[CS] 자바의 정석 독서 #3 - float, double, 부동소수점, 그리고 오차  (0) 2025.09.20
인프런 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의 후기  (0) 2025.09.20
'언어공부/Java | Kotlin' 카테고리의 다른 글
  • [CS] 자바의 정석 독서 #6 - 클래스와 메서드
  • [CS] 자바의 정석 독서 #6 - 객체지향 프로그래밍, OOP란 무엇인가?
  • [CS] 자바의 정석 독서 #4 - 형변환
  • [CS] 자바의 정석 독서 #3 - float, double, 부동소수점, 그리고 오차
Radiata
Radiata
개발을 합니다.
  • Radiata
    DDD
    Radiata
  • 전체
    오늘
    어제
    • 분류 전체보기 (211)
      • 신년사 (3)
        • 2025년 (2)
        • 2026년 (1)
      • CS (59)
        • JVM (12)
        • 백엔드 (20)
        • 언어구현 (1)
        • 객체지향 (1)
        • 논리회로 (5)
        • 컴퓨터구조 (9)
        • 데이터베이스 (1)
        • 컴퓨터 네트워크 (10)
      • 언어공부 (64)
        • Java | Kotlin (48)
        • JavaScript | TypeScript (9)
        • C | C++ (6)
      • 개인 프로젝트 (11)
        • [2025] Happy2SendingMails (3)
        • [2026] 골든리포트! (8)
        • [2026] 순수자바로 개발하기 (0)
        • 기타 이것저것 (0)
      • 팀 프로젝트 (29)
        • [2025][GDG]홍대 맛집 아카이빙 프로젝트 (29)
      • 알고리즘 (13)
        • 백준풀이기록 (11)
      • 놀이터 (0)
      • 에러 수정일지 (2)
      • 고찰 (24)
        • CEOS 23기 회고록 (2)
  • 블로그 메뉴

    • CS
    • 언어공부
    • 개인 프로젝트
    • 팀 프로젝트
    • 알고리즘
    • 고찰
    • 신년사
    • 컬러잇 개발블로그
  • 링크

    • 컬러잇 개발블로그
  • 공지사항

  • 인기 글

  • 태그

    144
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Radiata
[CS] 자바의 정석 독서 #5 - 연산자
상단으로

티스토리툴바