목표
자바가 제공하는 다양한 연산자를 학습하세요.
학습할 것
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선 순위
- (optional) Java 13. switch 연산자
산술 연산자
산술 연산자에는 사칙 연산자와 나머지 연산자가 있다. 사칙 연산자 (+, -, *, /)는 일상생활에서도 빈번히 쓰이기 때문에 주의 사항을 위주로 학습했다.
class Operator {
public static void main(String[] args) {
int a = 10;
int b = 4;
System.out.println("%d / %d = %d", a, b, a/b); // 10 / 4 = 2
System.out.println("%d / %f = %f", a, float(b), a/float(b)); // 10 / 4.000000 = 2.500000
}
}
10 나누기 4는 2.5인데, 첫 번째 출력문은 2를 출력하고 있다. 이는 두 피연산자 모두 int 타입이기 때문이다. 그래서 int 타입을 반환하기 때문에 실제 결과는 2.5일지라도 소수점을 버리고 2를 반환한다. 그래서 올바른 결과를 얻기 위해서는 두 피연산자 중 한 쪽을 실수형으로 캐스팅해줘야 한다. 그래야 다른 한 쪽도 같이 실수형으로 자동 형변환되어 원하는 값을 얻을 수 있다.
또한 피연산자가 정수형인 경우 0으로 나눌 수 없다. 만일 0으로 나눈다면 ArithmeticException
에러가, 0.0f 나 0.0d 처럼 부동 소수점값으로 나눈다면 Infinity
가 출력된다.
class Operator {
public static void main(String[] args) {
int a = 1_000_000;
int b = 2_000_000;
long c = a * b;
long d = 1_000_000 * 1_000_000;
long e = 1_000_000 * 1_000_000L;
System.out.println(c); // -1454759936
System.out.println(d); // -727379968
System.out.println(e); // 1000000000000
}
}
그러면 c가 왜 2000000000000 이 나오지 않는지 알 수 있을 것이다. long 의 범위가 더 크지만, 연산결과가 int 이기 때문에 전혀 다른 값이 출력된 것이다. d는 오버플로우가 발생한 예이다. int 의 최대값이 *2 * 109* 이기 때문이다.
나머지 연산자(%)는 왼쪽 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 반환한다. 기본적인 나눗셈처럼 0으로 나누는 것은 안되며, 음수로 나누는 것은 허용한다. 음수로 나눈 나머지는 부호를 무시하고 계산한 후 왼쪽 피연산자의 부호를 붙이면 된다.
System.out.println(10 % -8); // 2
System.out.println(-10 % 8); // -2
System.out.println(-10 % -8); // -2
비트 연산자
비트 연산자는 피연산자를 비트단위로 논리 연산한다. 이 때 피연산자는 정수만 허용한다.
- | (OR) : 피연산자 중 한 쪽 값이 1이면 1, 그 외에는 0
- 특정 비트의 값을 변경할 때 사용
- & (AND) : 피연산자 양쪽 모두 1이어야만 1, 그 외에는 0
- 특정 비트의 값을 뽑아낼 때 사용
- ^ (XOR) : 피연산자의 값이 서로 다를 때만 1, 같을 때는 0
- 간단한 암호화에 사용
관계 연산자
관계 연산자는 비교 연산자라고도 불리는데, 두 피연산자를 비교할 때 사용한다. 주로 조건식에 사용되며 연산결과는 오직 true 아니면 false 이다.
- 대소비교 연산자
- '<' : 좌변 값이 작으면 true, 아니면 false
- '>' : 좌변 값이 크면 true, 아니면 false
- '<=' : 좌변 값이 작거나 같으면 true, 아니면 false
- '>=' : 좌변 값이 크거나 같으면 true, 아니면 false
- 등가비교 연산자
- '==' : 두 값이 같으면 true, 아니면 false
- '!=' : 두 값이 다르면 true, 아니면 false
참고로 자바에서 두 문자열을 비교할 때에는 '=='가 아닌 equals() 메서드를 사용해야 한다.
논리 연산자
논리 연산자는 둘 이상의 조건을 연결하여 하나의 식으로 표현할 수 있게 한다.
- || (OR) : 피연산자 중 어느 한 쪽만 true면, 결과 true
- && (AND) : 피연산자 양쪽 모두 true여야만 결과 true
- ! (NOT) : 피연산자가 true면 false로, false면 true로 반환
instanceof
instanceof 는 파이썬만 사용하는 내게는 좀 생소했다. 객체 타입을 확인하는 연산자로 형변환이 가능한지 여부를 true / false 로 반환해준다.
class Parent {
...
}
class Child extends Parent {
...
}
public class InstanceOf {
public static void main(String[] args) {
Parent parent = new Parent();
Child child = new Child();
System.out.println(parent instanceof Parent); // true
System.out.println(parent instanceof Child); // false
System.out.println(child instanceof Parent); // true
System.out.println(child instanceof Child); // true
}
}
Child 클래스는 Parent 클래스를 상속했다. 즉, Parent 가 더 상위 클래스이기 때문에 하위 클래스로 형변환이 불가능하다.
assignment(=) operator
assignment operator 는 변수에 값을 대입할 때 사용하는 대입 연산자이다.
int a = 10;
Child child = new Child();
단순히 변수에 값을 넣는 개념에서 확장되어 객체를 참조하기 위해 할당하는 데에도 사용된다. 또한 아래와 같은 복합 대입 연산자도 있다.
- i += x : i = i + x
- i -= x : i = i - x
- i *= x : i = i * x
- i /= x : i = i / x
- i %= x : i = i % x
화살표(->) 연산자
화살표 연산자는 java 8 이상의 람다식에서 익명함수를 만들 때 사용한다. 람다함수 (익명함수)의 장단점은 다음과 같다.
-
장점
- 코드의 간결성
- 불필요한 연산 최소화
- 병렬처리 가능
-
단점
- 까다로운 호출
- 과하게 사용하면 오히려 가독성 떨어짐
-
람다 표현식
- (매개변수) ->
- () ->
- 매개변수가 하나일 경우 생략 가능
- (매개변수) -> 함수몸체
- 함수몸체가 단일 실행문이면 괄호 생략 가능
- (매개변수) ->
- 함수몸체가 return문으로만 구성되어 있는 경우 괄호 생략 불가능
class Temp {
...
}
class Lambda {
public static void main(String[] args) {
Temp temp = new Temp() { // 내부 익명 클래스
@Overide
public void print() {
System.out.print("lambda");
}
}
temp.print();
}
}
따라서 위와 같은 코드를 아래처럼 짧게 쓸 수 있다.
class Lambda {
public static void main(String[] args) {
Temp temp = () -> System.out.print("lambda");
}
}
3항 연산자
3항 연산자를 사용하면 if문 을 획기적으로 줄일 수 있다. 조건식 ? 참인 경우 : 거짓인 경우 이런 식으로 구성되는데 바로 예제를 보자.
result = (x > y) ? x : y;
x 가 y 보다 크면 x 를 반환하고, 반대의 경우에는 y 를 반환한다는 뜻이다. 원래대로 if문 을 사용한다면 다음과 같을 것이다.
if (x > y)
result = x;
else
result = y;
연산자 우선 순위
연산자 우선 순위는 대부분 상식적인 선에서 해결된다. 몇 가지 예제를 보면 "그렇구나" 하고 금방 이해할 수 있다.
- -x + 3
- 단항 연산자가 이항 연산자보다 우선순위가 높기 때문에 x의 부호를 바꾼 다음 3을 더한다.
- x + 3 * y
- 곱셈과 나눗셈이 덧셈과 뺄셈보다 우선순위가 높기 때문에 3과 y를 곱한 후 x를 더한다.
- x + 3 > y - 2
- 산술 연산자가 비교 연산자보다 우선순위가 높기 때문에 '>' 좌항 우항을 각각 계산한 후 비교한다.
- x > 3 && x