프로그래밍 언어/Java + Kotlin

[Java] 스터디 3주차: 연산자

2021. 6. 23. 17:29
목차
  1. 연산자와 피연산자
  2. 식과 대입연산자
  3. 연산자의 기능별 분류
  4. 산술 연산자
  5. 비트 연산자
  6. 비교 연산자
  7. 논리 연산자
  8. 기타 연산자
  9. 연산자 우선순위
  10. 참고

연산자와 피연산자

연산자는 '연산을 수행하는 기호'를 의미한다. 연산자가 연산을 수행하기 위해선 반드시 연산의 대상이 있어야 하는데, 이것을 피연산자(operand)라고 한다. 피연산자에는 상수, 변수, 식 등이 있다.

  • 연산자(operator): 연산을 수행하는 기호(+, -, *, / 등)
  • 피연산자(operand) 연산자의 작업 대상(변수, 상수, 리터럴, 수식)

대부분의 연산자는 두 개의 피연산자를 필요로 하지만, 하나 또는 세 개의 피연산자를 필요로 하는 연산자도 있다. 연산자는 피연산자로 연산을 수행하고 나면 항상 결과값을 반환한다.

 

식과 대입연산자

식(expression)

연산자와 피연산자를 조합하여 계산하고자 하는 바를 표현한 것을 '식(expression)'이라고 하고, 이러한 식을 계산하여 결과를 얻는 것을 '식을 평가(evaluation)한다'고 한다. 이때, 하나의 식을 평가(계산)하면, 단 하나의 결과를 얻는다. 만약 x의 값이 5라면, 아래의 식을 평가한 결과는 23이 된다. 

4 * x + 3

이렇게 작성한 식을 자바 프로그램 내 포함시키려면 식의 끝에 세미콜론(;)을 붙여서 문장(statement)로 만들어야 한다.

4 * x + 3; // 문장(statement)
-> 4 * 5 + 3;
-> 23;

 

대입연산자

이와 같이 식이 평가되어 결과(23)를 얻더라도, 이 값은 어디에도 쓰이지 않기 때문에 위의 문장은 아무런 의미가 없다. 그래서 대입 연산자(=)를 이용해 변수와 같이 값을 저장할 수 있는 공간에 결과를 저장해야 한다.

y = 4 * x + 3;
-> y = 4 * 5 + 3;
-> y = 23;

 

연산자의 기능별 분류

종류 연산자 설명
산술 연산자 + - * / % << >> 사칙연산(+, -, *, /)과 나머지 연산
비교 연산자 > < >= <= == != 크고 작음과 같고 다름을 비교
논리 연산자 && || ! & | ^ ~ '그리고(AND)'와 '또는(OR)'으로 조건을 연결
대입 연산자 = 우변의 값을 좌변에 저장
기타 (type) ? : instanceof 형변환 연산자, 삼항 연산자, instanceof연산자

연산자는 위의 표와 같이 크게 산술, 비교, 논리, 대입 연산자 4가지로 나눌 수 있다.

 

산술 연산자

  • 일상생활의 수학과 동일하게 곱셈(*), 나눗셈(/), 나머지(%) 연사자가 덧셈(+), 뺄셈(-) 연산자보다 우선순위가 높아 먼저 처리된다.
  • 피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없다(0으로 나눈다면 에러가 발생).

 

예제1

...
int a = 10;
int b = 10;

System.out.println("%d / %d = %d", a, b, a / b); // 10 / 4 = 2
System.out.println("%d / %f = %f", a, (float)b, a / b); // 10 / 4.000000 = 2.500000

 

나누기 연산자의 두 피연산자가 모두 int타입인 경우, 연산결과 역시 int타입이다. 그래서 실제 연산결과는 2.5일지라도 int타입의 값인 2를 결과로 얻는다. int타입은 소수점을 지정하지 못하므로 정수가 남고 소수점 이하는 버려지기 때문이다. 이 경우, 반올림이 발생하지 않는다.

10(int) / 4(int) -> 2(int) // 소수점 이하는 버려진다.

올바른 연산결과를 얻기 위해서는 다음과 같이 두 피연산자 중 어느 한 쪽을 실수형으로 형봔환해야 한다. 그렇게 되면 다른 한 피연산자도 실수형으로 자동 형변환되어 실수형의 값을 결과로 얻을 수 있다.

10(int) / 4.0f(float) -> 10.0f(float) / 4.0f(float) -> 2.5f(float)

 

예제 2

...
byte a = 10;
byte b = 10;
byte c = a + b;

System.out.printLn(c); // 에러 발생!

이 예제를 컴파일하면 에러가 발생한다. a와 b는 모두 int형보다 작은 byte형이기 때문에 연산자 '+'는 이 두개의 피연산자들의 자료형을 int형으로 변환한 다음 연산을 수행한다. 그래서 'a+b'의 연산결과는 byte형이 아닌 int형(4 byte)인 것이다. 4byte의 값을 1byte의 변수에 형변환없이 저장하려고 했기 때문에 에러가 발생하는 것이다.

 

앞서 2주차에서 형변환에 대해 언급한 적이 있다. 크기가 작은 자료형의 변수를 큰 자료형의 변수에 저장할 때는 자동으로 형변환되지만, 반대로 큰 자료형의 값을 작은 자료형의 변수에 저장하기 위해선 명시적으로 형변환 연산자를 사용하여 변환해줘야 한다.

byte c = (byte) (a + b); // 20

이처럼 자바는 파이썬이나 자바스크립트 같은 동적타입 언어와 다르게 사칙연산 시 자료형의 크기를 항상 고려해야 한다.

 

비트 연산자

비트 연산자는 피연산자를 비트단위로 논리 연산한다. 피연산자를 이진수로 표현했을 때의 각 자리를 아래의 규칙에 따라 연산을 수행하며, 피연산자로 실수는 허용하지 않고 정수(문자 포함)만 허용한다.

  • | (OR연산자): 피연산자 중 한 쪽의 값이 1이면, 1을 결과로 얻는다. 그 외에는 0을 얻는다.
  • & (AND연산자): 피연산자 양 쪽이 모두 1이어야만 1을 결과로 얻는다. 그 외에는 0을 얻는다.
  • ^ (XOR연산자): 피연산자의 값이 서로 다를 때만 1을 결과로 얻는다. 같을 때는 0을 얻는다.
x y x | y x & y x ^ y
1 1 1 1 0
1 0 1 0 1
0 1 1 0 1
0 0 0 0 0

 

비트 전환 연산자 ~

이 연산자는 피연산자를 2진수로 표현했을 때, 0은 1로, 1은 0으로 바꾼다. 논리부정 연산자 '!'와 유사하다.

x ~x
1 0
0 1

 

쉬프트 연산자 << >>

이연산자는 피 연산자의 각 자리(2진법으로 표현했을 때)를 오른쪽 또는 왼쪽으로 이동(shift)시킨다.  이때, 자리이동으로 저장범위를 벗어난 값들은 버려지고, 빈자리는 0으로 채워진다. 

  • 왼쪽(<<)으로 1만큼 이동하는 연산은 2를 곱하는 연산과 동일하다.
    • x << n == x * 2^n
  • 오른쪽(>>)으로 1만큼 이동하는 연산은 2로 나누는 연산과 동일하다. 
    • x > n == x / 2^n

 

비교 연산자

비교 연산자는 두 피연산자를 비교하는 데 사용된다. 주로 조건문과 반복문의 조건식에 사용되며, 연산결과는 오직 true와 false 둘 중의 하나이다. 비교 연산자 역시 이항 연산자이므로 비교하는 피연산자의 타입이 서로 다를 경우에는 자료형의 범위가 큰 쪽으로 자동 형변환하여 피연산자의 타입을 일치시킨 후에 비교한다.

 

대소비교 연산자 < > <= >=

두 피연산자의 값의 크기를 비교하는 연산자이다. 기본형 중에서는 boolean형을 제외한 나머지 자료형에 다 사용할 수 있지만 참조형에는 사용할 수 없다.

 

등가비교 연산자 == !=

두 피연산자의 값이 같은지 또는 다른지를 비교하는 연산자이다. 대소비교 연산자와는 달리, 참조형을 포함한 모든 자료형에 사용할 수 있다. 기본형의 경우 변수에 저장되어 있는 값이 같은지를 알 수 있고, 참조형의 경우 객체의 주소값을 저장하기 때문에 두 개의 피연산자(참조변수)가 같은 객체를 가리키고 있는지를 알 수 있다. 기본형과 참조형은 서로 형변환이 가능하지 않기 때문에 등가비교 연산자로 기본형과 참조형을 비교할 수 없다.

 

문자열의 비교

두 문자열을 비교할 때는, 비교 연산자 '=='대신 equals()라는 메소드를 사용해야 한다. 비교 연산자는 두 문자열이 완전히 같은 것인지 비교할 뿐이므로 문자열의 내용이 같은지 비교하기 위해서는 다음과 같이 equals()를 사용해야 한다.

String str = new String("abc");

// equals()는 두 문자열의 내용이 같으면 true, 다르면 false
boolean resut = str.equals("abc") // 내용이 같으므로 result에 true가 저장된다.

 

논리 연산자

논리 연산자는 둘 이상의 조건을 '그리고(AND)'나 '또는(OR)'으로 연결하여 하나의 식으로 표현할 수 있게 해준다.

 

논리 연산자  && || !

  • || (OR결합): 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻는다.
  • && (AND결합): 피연산자 양쪽 모두 true여야 true를 결과로 얻는다.
  • ! (NOT): 피연산자가 true이면 false를, false면 true를 반환한다.
x y x || y x && y
true true true true
true false true false
false true true false
false false false false

 

효율적인 연산

논리 연산자의 또 다른 특징은 효율적인 연산을 한다는 것이다.

  • OR연산의 경우, 두 피연산자 중 어느 한 쪽만 참이어도 전체 연산결과가 참이므로 좌측 피연산자가 true면 우측 피연산자의 값은 평가하지 않는다.
  • AND연산의 경우, 두 피연산자 중 어느 한 쪽만 거짓이어도 전체 연산결과가 거짓이므로 좌측 피연산자가 false면 우측 피연산자의 값은 평가하지 않는다.

 

기타 연산자

조건 연산자 > :

조건 연사자는 조건식, 식1, 식2 모두 세 개의 피연산자를 필요로 하는 삼항 연산자이며, 삼항 연산자는 조건 연산자 하나뿐이다. 아래에서 조건식이 true라면 식1을 반환하고, false라면 식2를 반환한다.

조건식 ? 식 1 : 식2
1. 25 > 24 ? true : false -> true
2. 25 < 24 ? true : false -> false

 

복합 대입 연산자

대입 연산자는 다른 연산자(op)와 결합하여 'op='와 같은 방식으로 사용될 수 있다.

op= =
i += 3; i  = i + 3;
i -= 3; i = i - 3;
i *= 3; i = i * 3;
i /= 3; i = i / 3;
i %= 3; i = i % 3;
i <<= 3; i = i << 3;
i >>= 3; i = i >> 3;
i &= 3; i = i & 3;
i ^= 3; i = i ^ 3;
i |= 3; i = i | 3;
i *= 10 + j; i = i * (10 + j);

 

instanceof 연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof연산자를 사용한다. 주로 조건문에 사용되며, instanceof의 왼쪽에는 참조변수를, 오른쪽에는 타입(클래스명)이 피연산자로 위치한다. instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

// 출처: https://zzdd1558.tistory.com/124
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{
	...
}

 

연산자 우선순위

식에 사용된 연산자가 둘 이상인 경우, 다음의 표와 같이 연산자의 우선순위에 의해서 연산순서가 결정된다.

 

참고

자바의 정석(남궁성 저)

저작자표시 비영리 (새창열림)

'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글

[Java] 스터디 6주차: 상속  (0) 2021.07.07
[Java] 스터디 5주차: 클래스  (0) 2021.07.07
[Java] 스터디 4주차: 제어문  (0) 2021.06.24
[Java] 스터디 2주차: 자바 데이터 타입, 변수 그리고 배열  (0) 2021.05.27
[Java] 스터디 1주차: JVM은 무엇이며, 자바 프로그램은 어떻게 실행되는가  (0) 2021.05.20
  1. 연산자와 피연산자
  2. 식과 대입연산자
  3. 연산자의 기능별 분류
  4. 산술 연산자
  5. 비트 연산자
  6. 비교 연산자
  7. 논리 연산자
  8. 기타 연산자
  9. 연산자 우선순위
  10. 참고
'프로그래밍 언어/Java + Kotlin' 카테고리의 다른 글
  • [Java] 스터디 5주차: 클래스
  • [Java] 스터디 4주차: 제어문
  • [Java] 스터디 2주차: 자바 데이터 타입, 변수 그리고 배열
  • [Java] 스터디 1주차: JVM은 무엇이며, 자바 프로그램은 어떻게 실행되는가
코택
코택
코택
TaxFree
코택
전체
오늘
어제
  • 분류 전체보기 (369)
    • Spring (29)
      • Spring (18)
      • 스프링 핵심 원리 - 고급편 (11)
    • Spring Batch (4)
    • JPA (4)
    • CS (89)
      • 자료구조 (2)
      • 네트워크 (5)
      • 운영체제 (1)
      • 데이터베이스 (4)
      • SQL (7)
      • 알고리즘 이론 (4)
      • 알고리즘 문제 풀이 (66)
    • 웹 (28)
      • React.js (4)
      • Next.js (1)
      • Node.js (14)
      • FastAPI (4)
      • Django (5)
    • 프로그래밍 언어 (45)
      • Python (5)
      • Java + Kotlin (29)
      • JavaScript + TypeScript (11)
    • 테스트코드 (26)
      • ATDD, 클린 코드 with Spring (4)
      • 이규원의 현실 세상의 TDD: 안정감을 주는 코드.. (20)
    • 인프라 (6)
      • AWS (2)
      • Kubernetes (4)
    • 트러블슈팅 (25)
    • 책 (89)
      • Effective Java (54)
      • Effective Kotlin (14)
      • 도메인 주도 개발 시작하기: DDD 핵심 개념 정.. (11)
      • 웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 (6)
      • 도메인 주도 설계 첫걸음 (4)
    • Git (10)
    • 회고 (5)
    • etc (8)

블로그 메뉴

  • 홈
  • 방명록
  • 관리
  • GitHub
  • LinkedIn

공지사항

  • 스킨 관련

인기 글

태그

  • 깊이 우선 탐색
  • 파이썬
  • dp
  • atdd
  • http
  • Git
  • 브루트포스
  • Shortest Path
  • 장고
  • mysql
  • 그래프 탐색
  • fastapi
  • 백준
  • BOJ
  • 그래프

최근 댓글

최근 글

hELLO · Designed By 정상우.
코택
[Java] 스터디 3주차: 연산자
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.