목표
자바가 제공하는 다양한 연산자를 학습하세요.
학습할 것
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선순위
- (optional) Java 13. switch 연산자
산술 연산자
사칙 연산자 +-*/
우선순위는 일반적으로 알고 있는 것과 같다.(*,/ > +-)
- 이항 연산자는 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은 어디에서 왔을까
결국 자릿수 별로 쉬프트 연산을 해봤다.
![](https://blog.kakaocdn.net/dn/bFXzyb/btqVFA6KWIl/XLekquujolqQ3FusMIhHQk/img.png)
![](https://blog.kakaocdn.net/dn/cifbM7/btqVAIK2Gl6/zf6GPMUNzjfyY5uTF5JJkK/img.png)
당연하게도 5 <= n <= 31 까지는 결괏값이 0이다.
![](https://blog.kakaocdn.net/dn/bq7Apk/btqVzSmTbKh/qMJiD10kVAw2M6OUQvbEQK/img.png)
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
참조 변수가 참조하고 있는 인스턴스의 타입이 검사 대상 타입으로 형 변환이 가능한지 판단한다.
왼쪽에는 참조 변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치한다.
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)
자바의 정석 - 남궁 성
'IT > JAVA' 카테고리의 다른 글
자바 상속 - 백기선님 스터디 6주차 과제 (0) | 2021.02.19 |
---|---|
자바 클래스 - 백기선님 스터디 5주차 과제 (0) | 2021.02.13 |
자바 제어문 - 백기선님 스터디 4주차 과제 (0) | 2021.02.10 |
자바 데이터 타입, 변수 그리고 배열 - 백기선님 스터디 2주차 과제 (0) | 2021.02.02 |
JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 - 백기선님 스터디 1주차 과제 (0) | 2021.01.31 |