3주차 과제: 연산자
목표
자바가 제공하는 다양한 연산자를 학습하세요.
학습할 것
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선 순위
- (optional) Java 13. switch 연산자
산술 연산자
산술 연산자는 수학적인 계산에 사용되는 연산자입니다. 바로 예제를 통해 알아보자!
public class Parent {
public static void main(String[] args) {
int result = 1 + 2; //덧셈 연산자
System.out.println(result);
result = result - 1; //뺄셈 연산자
System.out.println(result);
result = result * 2; //곱하기 연산자
System.out.println(result);
result = result / 2; //나누기 몫 연산자
System.out.println(result);
result = result + 8;
result = result % 7; //나누기 나머지 연산자
System.out.println(result);
}
}
더하기 연산자(+)는 숫자와 숫자를 더할 때 사용되지만, 문자열과 문자열을 결합할 때도 사용됩니다.
public class Operation {
public static void main(String[] args) {
String firstString = "This is";
String secondString = " a concatenated string";
String thirdString = firstString + secondString;
System.out.println(thirdString); //This is a concatenated string
}
}
비트 연산자
비트 연산자는 데이터를 비트 단위로 연산합니다. 따라서 0과 1로 표현이 가능한 정수 타입이나 정수형으로 캐스팅이 가능한 자료형만 비트 연산이 가능합니다. 비트 연산자는 기능에 따라 비트 이동 연산자, 비트 논리 연산자로 구분합니다.
비트 이동 연산자(<<, >>, >>>)
비트 이동 연산자는 정수 데이터의 비트를 왼쪽 또는 오른쪽으로 이동시키는 연산을합니다.
- x << y : 정수 x의 각 비트를 y만큼 왼쪽으로 이동시킵니다. (빈자리는 0으로 채워집니다.)
- x >> y : 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킵니다. (빈자리는 정수 a의 최상위 부호비트와 같은 값으로 채워집니다.)
- x >>> y : 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킵니다. (빈자리는 0으로 채워집니다.)
2 << 3은 2를 32비트로 분해한 다음 왼쪽으로 3비트를 이동시키는 연산입니다. 이 때 맨 왼쪽 3비트는 밀려서 버려지게 되고 맨 오른쪽 빈자리에는 0으로 채워집니다. 그래서 채워진 2진수를 10진수로 변환하면 16이 됩니다.
16 >> 3은 16을 32비트로 분해한 다음 오른쪽으로 3비트를 이동시키는 연산입니다. 이 때 맨 오른쪽 3비트는 밀려서 버려지게 되고 맨 왼쪽 빈자리에는 0으로 채워집니다. 이를 10진수로 변환하면 2가 됩니다.
16 >>> 3은 오직 자바에만 있는 연산이며 >> 와 기본원리는 같습니다. 다만 다른 점은 맨 왼쪽에는 최상위 부호비트와 관계없이 무조건 0으로만 채워지게 됩니다. 그래서 최상위 부호비트가 1인 음수라 할지라도 >>> 연산을 해주게 되면 무조건 양수로만 나타나게 됩니다.
public class Operation {
public static void main(String[] args) {
System.out.println(2 << 3);
System.out.println(16 >> 3);
System.out.println(-16 >>> 3);
}
}
비트 논리 연산자
비트 논리 연산자는 그 대상이 boolean 타입일 경우에는 일반 논리 연산자로 활용되지만 대상이 정수형일 경우에는 비트 논리 연산자로 활용됩니다. 비트 연산은 두 값을 비트 단위로 나열한 다음 각 자릿수를 비트 연산자로 연산합니다. 각 자릿수의 연산은 독립적이며 다른 자릿수에 영향을 주지 않습니다.
- & (AND) : 두 비트 모두 1일 경우에만 연산 결과가 1
- | (OR) : 두 비트 중 하나만 1일 경우에만 연산 결과가 1
- ^ (XOR) : 두 비트 중 하나는 1이고 다른 하나는 0일 경우에만 연산 결과가 1 (서로 달라야 함.)
- ~ (NOT) : 비트 반전 (보수)
관계 연산자
비교 연산자라고도 하며, 수학 부등호를 생각하시면 됩니다. 관계 연산자의 결과는 true
, false
값인 boolean 타입으로 반환됩니다. 주로 제어문에서 많이 활용합니다.
public class Operation {
public static void main(String[] args) {
int a = 3;
System.out.println(a > 2); //true
System.out.println(a < 5); //true
System.out.println(a >= 5); //false
System.out.println(a <= 4); //true
System.out.println(a == 1); //false
System.out.println(a != 2); //true
}
}
논리 연산자
논리 연산자는 피연산자로 boolean 타입 또는 boolean 타입의 값을 결과로 하는 조건식만을 허용합니다.
- || (OR 연산자) : 피연산자 중 어느 한 쪽이 true이면 true.
- && (AND 연산자) : 피연산자 양 쪽 모두 true이면 true.
public class Operation {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
System.out.println(a || b); //true
System.out.println(a && b); //false
}
}
instanceof
2주차 글에서 잠깐 설명했지만 instanceof
는 객체 타입을 확인하는 연산자입니다. 형변환 가능여부를 확인하며, true/false를 반환합니다. 주로 상속 관계에서 부모 객체인지 자식 객체인지 확인하는데 사용합니다.
public class Parent {
public static void parentPrint() {
System.out.println("Parent.parentPrint");
}
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 Child); //true
System.out.println(child instanceof Parent); //true
}
}
class Child extends Parent {
public static void childPrint() {
System.out.println("Child.childPrint");
}
}
parent instanceof Parent
: Parent 인스턴스는 parent, 맞으니까 truechild instanceof Child
: Child 인스턴스는 child, 맞으니까 truechild instanceof Parent
: Parent 인스턴스는 child, Child 클래스는 Parent는 클래스를 상속받았으니까 true (이 때는 업캐스팅이 가능합니다.)parent instanceof Child
: Child 인스턴스는 parent, Child 클래스는 Parent 타입의 인스턴스화시킬 수 없습니다. 따라서 다운캐스팅을 할 수 없습니다. 만약 다운캐스팅을 하려고 한다면 먼저 업캐스팅 시킨 다음에 다운캐스팅 해주어야 합니다.
assignment(=) operator
대입 연산자라고도 하며, 대입 연산자는 변수에 값을 대입할 때 사용하는 이항 연산자입니다. 피연산자들의 결합 방향은 오른쪽에서 왼쪽입니다. 또한 자바에서는 대입 연산자와 다른 연산자를 결합하여 만든 다양한 복합 대입 연산자를 제공합니다.
public class Operation {
public static void main(String[] args) {
int num = 3;
num += 9;
num -= 2;
num *= 3;
num /= 10;
System.out.println(num);
}
}
그 밖에 더 있지만 위 4가지를 많이 사용합니다.
화살표(->) 연산자
화살표 연산자란 다른 말로 람다 표현식이라고 할 수 있습니다. 만약 자바스크립트를 사용하신 분이라면 이 람다 표현식이 어렵지 않게 느껴지실 것 같습니다. 바로 예제를 보도록하죠.
Foo interface
@FunctionalInterface
public interface Foo {
void printInt(int param);
}
Operation class (Main)
public class Operation implements Foo {
public static void main(String[] args) {
Operation operation = new Operation();
int x = 3;
Foo foo = new Foo() {
@Override
public void printInt(int param) {
System.out.println(param);
}
};
operation.printInt(x);
}
@Override
public void printInt(int param) {
System.out.println(param);
}
}
위 코드처럼 메소드 내에서 Foo 인터페이스를 받아와서 구현하려면 6줄이나 추가됩니다. 이를 람다 표현식을 사용하면 1줄로 만들 수 있어서 가독성이 좋아집니다.
Foo foo = (param) -> System.out.println(param);
이 부분은 람다식 주제에서 좀 더 자세히 다뤄보겠습니다.
3항 연산자
우리가 if문을 사용하면 코드라인 쓸데없이 길어지는 경향이 있습니다.
public class Operation {
public static void main(String[] args) {
int score = 92;
char grade;
if (score > 90) {
grade = 'A';
} else {
grade = 'B';
}
System.out.println(grade);
}
}
이 코드에서 if else
절만 5라인입니다. 하지만 삼항연산자를 사용하면 굉장히 간략히 보일 수 있습니다.
public class Operation {
public static void main(String[] args) {
int score = 92;
char grade = (score > 90) ? 'A' : 'B';
System.out.println(grade);
}
}
훨씬 가독성이 좋아보입니다. 하지만 삼항 연산자를 사용할 때 너무 많이 조건을 걸어버리면 보는 사람 입장에서 이 코드를 보고 이해하기 어려울 수 있으니 이 점만 주의하시면 될 것 같습니다. 만약 할당할 변수가 필요없다면 아래 코드처럼 해도 되겠죠.
public class Operation {
public static void main(String[] args) {
int score = 92;
System.out.println((score > 90) ? 'A' : 'B');
}
}
연산자 우선순위
기본적으로 연산자에는 우선순위가 있으며, 괄호의 우선순위가 제일 높고, 산술 > 비교 > 논리 > 대입 순서, 단항 > 이항 > 삼항 순서입니다. 사실.. 이걸 다 외울 수는 없고 만약 우선순위가 필요하다면 괄호()
를 사용하시기 바랍니다. 순서는 아래 링크를 참고하시면 됩니다.
https://toma0912.tistory.com/66
(optional) Java 13. switch 연산자
public class Operation {
public static void main(String[] args) {
String day = "THURSDAY";
switch (day) {
case "MONDAY":
case "WEDNESDAY":
case "FRIDAY":
System.out.println("운동 하는 날");
break;
default:
System.out.println("운동 쉬는 날");
}
}
}
기본적으로 자바 13 이전에는 switch 문법이 위 코드처럼 작성하면 됐었습니다. 자바 13 부터는 문법이 조금 바꼈는데 바뀐 이유를 다음 블로그에서는 이렇게 설명했습니다. (https://catch-me-java.tistory.com/31)
-> (정정) 자바 13부터 switch 문법이 바꼈다고 설명했는데 바뀐 것이 아니라 Switch Operator가 추가된 것입니다. 즉, 기존 switch 문법은 그대로 있습니다. 잘못 설명한 부분 정정하겠습니다.
- 코드가 불필요하게 장황하다.
- 에러 발생시 디버깅이 어렵다.
- Missing Break;
자바 13부터 yield
라는 산출값을 리턴이 가능합니다. 그 전에는 break
를 통해서 했지만 yield
를 사용하여 변수에 값을 넣을 수 있습니다.
public class Operation {
public static void main(String[] args) {
String day = "THURSDAY";
int day2 = switch (day) {
case "MONDAY":
case "WEDNESDAY":
case "FRIDAY":
System.out.println("운동 하는 날");
yield 1;
default:
System.out.println("운동 쉬는 날");
yield -1;
};
System.out.println(day2);
}
}
References
'Java' 카테고리의 다른 글
[자바 라이브 스터디] 05. 클래스 (0) | 2021.09.24 |
---|---|
[자바 라이브 스터디] 04. 제어문 (0) | 2021.09.23 |
[자바 라이브 스터디] 02. 자바 데이터 타입, 변수와 배열 (0) | 2021.09.16 |
[자바 라이브 스터디] 01. JVM과 자바 코드 (0) | 2021.09.15 |
[자바 라이브 스터디] 00. 자바 기본 공부 계획 (0) | 2021.09.13 |
댓글