▣ 목표
자바가 제공하는 다양한 연산자를 학습하세요.
▣ 학습할 내용
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선 순위
- (optional) Java 13. switch 연산자
▶ 3-0 용어 정리
연산자 (operator) : 연산을 수행하는 기호 (+, -, *, /, % 등)
피연산자(operand) : 연산자의 작업 대상 (변수, 상수, 리터럴, 수식 등)
▶ 3-1 산술 연산자(Arithmetic Operator)
기본 사칙 연산자(+, -, *, /)와 나머지 연산자(%)가 있다. 우선순위도 이미 알고있던 순서대로 곱셈, 나눗셈, 나머지 연산자의 우선순위가 높고, 덧셈과 뺄셈은 그 다음에 처리된다. 나눗셈의 경우 주의할 점은 나누는 피연산자가 정수형인 경우, 0으로 나누면 에러가 발생한다. (ArithmeticException 발생)
상대적으로 범위가 작은 타입의 연산도 주의해야한다. 아래 예시는 byte타입의 연산이다.
public class Main {
public static void main(String[] args) {
byte a=10;
byte b=20;
byte c=a+b; // 컴파일 에러 발생
System.out.println(c);
}
}
위의 코드는 컴파일 타임에 에러가 발생하기 때문에 아래 코드와 같이 명시적 형변환(Type Casting)이 필요하다. 단, 큰 자료형에서 작은 자료형으로 명시적 형변환을 할 때 값의 범위를 체크해야한다. 값의 범위를 넘어버리면 데이터 손실이 발생하여 정확한 결과 값을 얻을 수 없다. 반대로 작은 자료형에서 큰 자료형으로 변환하는 것은 데이터 손실이 발생하지 않는다. byte에서 int로 바뀐다면, bit 8자리는 그대로 보존하고 나머지 3byte(27bit)에 해당하는 자리는 0으로 채우게 된다.
public class Main {
public static void main(String[] args) {
byte a=10;
byte b=20;
byte c=(byte)(a+b); //OK!
System.out.println(c);
}
}
▶ 3-2 비트 연산자(Bitwise Operator)
▷ | (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 |
비트 전환 연산자에 의해 전환이 되고 나면, 부호있는 타입의 피연산자는 부호가 반대로 변경된다. (양수 -> 음수) 즉, 피연산자의 1의 보수를 얻을 수 있다. 그래서 비트 전환 연산자를 '1의 보수 연산자'라고도 부른다.
0 0 0 0 1 0 1 0 //10
↓
1 1 1 1 0 1 0 1 //-11
1 1 1 1 0 1 0 1
+ 0 0 0 0 0 0 0 1
-----------------------------
1 1 1 1 0 1 1 0 //-10
위의 예시와 같이 10진수 10을 비트전환 연산한 결과는 -11이 된다. 그리고 이 값을 10의 '1의 보수'이다. 1의 보수에 1을 더하면 음수가 되므로 -11에 1을 더하면 -10이 되므로 -11은 10의 '1의 보수'가 됨을 확인할 수 있다.
비트 전환 연산자는 피연산자의 타입이 int보다 작으면 int로 자동형변환(Type Casting)한 후에 연산하기 때문에 연산결과는 32자리의 2진수가 된다.
▷쉬프트 연산자 '<<' OR '>>' : 피연산자의 각 자리(2진수로 표현했을 때)를 '오른쪽(>>)' 또는 '왼쪽(<<)'으로 이동한다고 하여 '쉬프트 연산자(shift operator)'라고 불린다.
예를 들어 8<<2 는 왼쪽 피연산자인 10진수 8의 2진수를 왼쪽으로 2자리 이동한다는 뜻이다. 반대로 8>>2는 2진수를 오른쪽으로 2자리 옮긴다는 의미이다.
왼쪽 쉬프트 연산자의 경우를 먼저 보자면,
1) 10진수 8을 2진수로 표현하면 '00001000'이 된다. 이 8의 2진수를 왼쪽으로 2자리 이동하고 나머지는 빈자리는 0으로 채운다.
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
2) 빈자리를 채운 빨간 숫자 0이 있고 범위를 벗어난 파란색 숫자 0이 있다. 범위를 벗어난 파란 숫자는 버려지고 빨간 숫자만 남는다.'8<<2'의 결과는 2진수로 '001000000'이 되고, 이 2진수를 다시 10진수로 변환하면 32가 된다.
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
이제 오른쪽 쉬프트 연산자의 경우를 보자,
1) 8의 2진수를 오른쪽으로 2자리 이동하고 나머지는 빈자리는 0으로 채운다. (단, 피연산자(여기서는 8)이 음수라면 빈자리를 1로 채운다.)
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
2) 빈자리를 채운 빨간 숫자 0이 있고 범위를 벗어난 파란색 숫자 0이 있다. 범위를 벗어난 파란 숫자는 버려지고 빨간 숫자만 남는다.'8<<2'의 결과는 2진수로 '001000000'이 되고, 이 2진수를 다시 10진수로 변환하면 32가 된다.
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
식으로 편하게 외우려면,
x<<n은 x * 2^n의 결과와 같다.
x>>n은 x / 2^n의 결과와 같다.
로 외워두면 될 것 같다.
편하게 나눗셈, 곱셈할 수 있는데 왜 쉬프트 연산자를 제공할까? 속도에서 차이가 나기 때문이다. 가독성이 중요하다면 나눗셈, 곱셈 사용해도 되지만, 속도가 중요시되는 프로그램 개발에선 쉬프트 연산을 활용하는 것이 좋다.
▶ 3-3 관계 연산자(비교 연산자 : Comparison Operator)
관계 연산자는 자주 사용하니까 간단히 정리하고 넘어가야겠다.
▷ 대소비교 연산자
연산자 | 연산결과 |
> | 좌변 값이 크면 true, 아니면 false |
< | 좌변 값이 작으면 true, 아니면 false |
>= | 좌변 값이 크거나 같으면 true, 아니면 false |
<= | 좌변 값이 작거나 같으면 true, 아니면 false |
▷ 등가비교 연산자
연산자 | 연산결과 |
== | 두 값이 같으면 true, 아니면 false |
!= | 두 값이 다르면 true, 아니면 false |
▷ 문자열의 비교
두 문자열을 비교할 때는, 연산자 '==' 대신 equals()라는 메서드를 사용해야 한다. equals()는 비교하는 두 문자열이 같으면 true, 다르면 false를 리턴한다.
▶ 3-4 논리 연산자(Logical Operator)
|| (OR 결합) : 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻는다.
&& (AND 결합) : 피연산자 양쪽 모두 true이어야 true를 결과로 얻는다.
-------------------------------------------------------------------------------
! (논리 부정 연산자) : 피연산자가 true이면 false를, false이면 true를 리턴한다.
▶ 3-5 instanceof
참조변수 instanceof 타입(클래스명)
-> 연산의 결과로 true가 나온다는 것은 참조변수가 오른쪽 타입으로 형변환이 가능하다는 것을 의미한다.
▶ 3-6 Assignment(=) Operator
대입연산자라고도 불린다. 대입 연산의 진행방향은 오른쪽에서 왼쪽이기 때문에 'x=y=3;'에서 'y=3'이 먼저 수행되고 그 다음에 'x=y'가 수행된다.
▷ 복합 대입 연산자
다른 연산자와 결합하여 '{op}='과 같은 방식으로 사용할 수 있다. 예를 들어 +=, -=, *=, /=, %=등 결합된 두 연산자는 공백없이 사용해야 한다. 풀어서 작성하면
i = i+3;
i = i-3;
i = i*3;
i = i/3;
i = i%3;
이렇게도 작성할 수 있다.
▶ 3-7 화살표 (->) 연산자
화살표 연산자는 람다식을 작성할 때 메서드이름과 반환타임을 제거하고 매개변수 선언부와 바디 사이에 '->'를 추가하는 방식으로 쓰인다.
▶ 3-8 3항 연산자
▶ 3-9 연산자 우선순위
▶ 3-10 (optional) Java 13, Switch Operator
기존의 swtich의 case : 에서 콜론이 빠지고 arrow operator을 사용할 수 있게 되었다. break대신 yield을 사용한다. 다중 구문 적용시, throw구문을 사용할 때, expression이 아닌 경우는 중괄호로 감싼다.
public class Test {
public static void main(String[] args) {
countNum(2);
}
public static void countNum(int i){
switch(i){
case 1 -> System.out.println("하나");
case 2 -> System.out.println("둘");
case 3 -> System.out.println("셋");
default -> System.out.println("3이상 숫자");
}
}
}
백기선님의 자바 라이브 스터디 커리큘럼을 따라 공부하고 있습니다.
잘못된 점이나 보충할 부분이 있으면 코멘트 남겨주세요
작은 조언이 저에겐 성장의 원동력이 됩니다 :-)
'Java' 카테고리의 다른 글
[자바 스터디] #9 - 예외처리 (0) | 2021.02.18 |
---|---|
[자바 스터디] #7 - 패키지 (0) | 2021.02.17 |
[자바 스터디] #8 - 인터페이스 (1) | 2021.02.16 |
[자바 스터디] #2 - 데이터 타입, 변수 그리고 배열 (0) | 2021.01.27 |
[자바 스터디] #1 - JVM과 컴파일 (0) | 2021.01.26 |
댓글