본문 바로가기

IT/JAVA

자바 연산자 - 백기선님 스터디 3주차 과제

목표

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

학습할 것

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

산술 연산자

사칙 연산자 +-*/

우선순위는 일반적으로 알고 있는 것과 같다.(*,/ > +-)

 

- 이항 연산자는 int보다 작은 타입의 피연산자를 int로 자동 형 변환한다.

int로 형변환하여 연산하였기때문에 byte에 넣으려면 컴파일 에러가 난다. 

 

- 상수나 리터럴 간의 연산은 실행 과정 동안 변하는 값이 아니기 때문에 컴파일 시 컴파일러가 계산해서 결괏값으로 대체한다.

 

- 두 피연산자의 타입이 같을 경우 연산 결과 역시 같은 타입을 가진다.

따라서 다음과 같은 결과가 나올 수 있다.

1.5라고 생각할 수 있지만 int는 정수이므로 소수점 단위의 값은 버린다.

 

 

int의 범위를 넘어섰기때문에 오버플로우가 발생하여 예상했던 결과와 다른 값이 나온다.

 

위 두 케이스에서 원하는 값을 얻으려면 피연산자 중 하나의 타입을 원하는 결과 타입형으로 변환해주면 된다.

그럼 다른 피연산자도 자동형 변환되어 연산된다.

 

- 두 피연산자의 타입이 다를 경우 더 큰 피연산자의 타입으로 변환되어 연산된다.

- 정수형의 피연산자는 0으로 나눌 수 없다.

- 부동 소수점 값인 0.0f, 0.0d로 나누는 것은 가능하지만 결괏값은 Infinity(무한대)이다.

 

나머지 연산자 %

나머지 값을 결과로 반환하는 연산자이다. 

0으로 나눌 수 없고 피연산자로 정수만 허용한다.

 

 

비트 연산자 & | ^ ~ << >>

비트 연산자는 피연산자를 비트단위로 논리 연산한다.

피연산자로 정수만 허용한다.

& (AND연산자)  피연산자 모두 1일때만 1, 나머지는 0
|  (OR연산자) 둘 중 하나 이상 1일때 1, 나머지는 0
^ (XOR연산자) 두 값이 다를 때만 1, 같을때는 0
피연산자 연산자
X Y & | ^
1 1 1 1 0
1 0 0 1 1
0 1 0 1 1
0 0 0 0 0

 

비트 전환 연산자 ~

피연산자를 2진수로 표현했을 때 0은 1로 1은 0으로 바꾼다.

X ~X
1 0
0 1

 

쉬프트 연산자 << >>

피연산자를 2진수로 표현했을 때 각 자리를 오른쪽(>>) 또는 왼쪽(<<)으로 이동하는 연산자이다.

<< 연산자는 피연산자의 부호와 상관없이 빈칸을 0으로 채우지만

>> 연산자는 부호를 유지하기 위해 음수인 경우 빈칸을 1로, 양수일 경우는 빈칸을 0으로 채운다.

 

2진수의 자릿수를 옮기는 것으로 아래와 같이 정리할 수 있다.

x << n 은 x * 2ⁿ의 결과와 같고

x >> n 은 x / 2ⁿ의 결과와 같다.

 

위 연산 시 n의 값이 자료형의 bit 수보다 크면 자료형의 bit수로 나눈 나머지만큼만 이동한다. *

ex) int는 4byte(32bit)이므로 8 >> 34 를하면 34/32의 나머지인 2만큼만 이동해서 8 >> 2를 수행한다.

 

쉬프트 연산자는 /*를 사용하는 것보다 속도가 빠르다.

 

더보기

* 자바의 정석에서 해당 부분을 설명하면서 아래와 같은 문구가 있었다.

"int타입이 4byte(32bit)인 경우, 자릿수를 32번 바꾸면 결국 제자리로 돌아오기 때문에, '8 >> 32'는 결국 아무일도 하지 않는다."

 

이 부분을 읽으면서 의문이 생겼다. 바로 앞장에서 자리수를 옮기고 빈자리는 0으로 채운다고 했는데 그럼 32번을 옮기면 다 탈락하고 0이 되어야 하는 거 아닌가..? 버려졌던 1은 어디에서 왔을까

결국 자릿수 별로 쉬프트 연산을 해봤다.

8 >> 5
8 >> 31

당연하게도 5 <= n <= 31 까지는 결괏값이 0이다.

8 >> 32

 32번 시프트 하면 8 >> 0과 결과가 같다..!

여기까지 해보고 그냥 내부적으로 '이동 카운트 = 입력한 숫자 % 자료형 사이즈' 인가 보다 하고 넘어갔다.

자세히 아는 사람이 있으면 친절히 나에게 설명해주면 좋겠다.. :)

 

 

관계 연산자

 

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

기본형 중 boolean을 제외한 나머지 자료형에 사용 가능하다.

참조형에는 사용이 불가하다.

비교연산자 연산결과
> 좌변이 크면 true, 아니면 false
< 좌변이 작으면 true, 아니면 false
>= 좌변이 크거나 같으면 true, 아니면 false
< 좌변이 작거나 같으면 true, 아니면 false

 

등가 비교 연산자 == !=

기본형, 참조형 모두 사용 가능하다.

기본형은 변수에 저장되어 있는 값을 비교하고

참조형은 같은 객체를 가리키고 있는지를 확인한다.

실수형은 근삿값으로 저장되므로 오차가 발생할 수 있다.

문자열을 비교할 때 ==, !=는 주소 값을 비교하기 때문에 문자열 내용을 비교하려면 equalse()를 사용해야 한다.

비교연산자 연산결과
== 두 값이 같으면 true, 다르면 false
!= 두 값이 다르면 true, 같으면 false

 

논리 연산자 && || !

논리 연산자는 효율적인 연산을 한다.

&&는 두 값이 모두 true여야 true이기 때문에 좌측 피연산자가 false일경우 우측 피연산자 값을 평가하지 않는다.

||는 둘 중 하나만 true여도 true이기때문에 좌측 피연산자가 true일 경우 우측 피연산자 값을 평가하지 않는다.

논리 연산자 연산결과
&& 두 값이 모두 true여야 true, 아니면 false
|| 두 값 중 하나만 true여도 true, 아니면 false
피연산자 연산자
X Y && ||
true true true true
true false false true
false true false ture
false false false false

 

논리 부정 연산자 !

피연산자가 true일 경우 false를, false일 경우 true를 반환한다.

X !X
true false
false true

 

 

instanceof

참조 변수가 참조하고 있는 인스턴스의 타입이 검사 대상 타입으로 형 변환이 가능한지 판단한다.

왼쪽에는 참조 변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치한다.

결과가 false인 3번 케이스를 형변환 하려하면 ClassCastException이 발생한다. 결과가 true인 2번 케이스는 오류가 발생하지 않았다.

 

assignment(=) operator

대입 연산자는 변수와 같은 저장 공간에 값 또는 수식의 연산 결과를 저장하는 데 사용된다.

오른쪽 피연산자(rvalue) 값을 왼쪽 피연산자(lvalue)에 저장하며 가장 낮은 우선순위를 가진다.

연산의 방향은 오른쪽에서 왼쪽으로 수행되어 x = y = 3과 같은 식이 있을 때

y = 3이 먼저 수행된 후 x = y가 수행된다.

rvalue에는 변수, 수식, 상수 등이 모두 올 수 있지만 lvalue는 변수처럼 값을 변경할 수 있는 것만 올 수 있다.

 

= operator는 산술 연산자, 비트 연산자와 함께 쓸 수 있다.

연산자 연산 결과
+= a += b 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 a = a >> b

 

 

화살표(->) 연산자

람다식이라고 부른다.

메서드를 하나의 식(expression)으로 표현한 것이다.

(매개변수) -> {식}와 같이 사용된다.

 

메서드를 람다식으로 표현하면 메서드의 이름과 반환 값이 없어지므로 익명 함수(anonymous function)이라고도 한다.

int max (int a, int b){
	return a > b ? a : b;
}

(int a, int b) -> {return a > b ? a : b;}

(int a, int b) -> a > b ? a : b

(a, b) -> a > b ? a : b
    

위 네 개의 표현은 모두 같은 결과를 가진다.

식 표현에서 중괄호{}를 생략할 수 있지만 괄호 안에 return 문장이 있을 경우에는 생략하지 못한다.

 

매개변수에서 소괄호()는 매개변수가 하나이거나 타입을 작성하지 않을 때만 생략 가능하다.

매개변수 타입은 추론이 가능한 경우 생략할 수 있는데 대부분 생략이 가능하다.

(int a) -> a * a
(a) 	-> a * a
a 	-> a * a

 

3항 연산자

조건식 ? 식1 : 식2

피연산자 세 개를 사용하는 연산자이다.

조건식의 값이 boolean값을 가지고, 그 조건을 사용해 값 또는 수식을 결정할 때 사용할 수 있다.

조건식이 true일 때는 식 1의 값을 결괏값으로 갖고 false일때는 식2의 값을 결과값으로 갖는다.

 

 

연산자 우선순위

연산자 유형별 우선순위

산술 > 비교 > 논리 > 대입

 

단항 연산자의 우선순위가 이항 연산자보다 높다.

단항 > 이항 > 삼항

 

단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽이다.

 

산술 연산자

일반적으로 알고 있는 순위와 같다.

* / 의 우선순위가  +-보다 높다.

 

출처: 자바의 정석 - 남궁성

 


Reference)

자바의 정석 - 남궁 성