[백기선님의 자바 라이브 스터디] 3주차 - 연산자
www.youtube.com/watch?v=HLnMuEZpDwU
목표
자바가 제공하는 다양한 연산자를 학습하세요.
학습할 것
- 산술 연산자
- 비트 연산자
- 관계 연산자
- 논리 연산자
- instanceof
- assignment(=) operator
- 화살표(->) 연산자
- 3항 연산자
- 연산자 우선 순위
- (optional) Java 13. switch 연산자
간단한 용어 정리
정리하기에 앞서 관련용어를 정리해보겠습니다.
연산 ( operations ) | 프로그램에서 데이터를 처리하여 결과를 얻어내는 것 |
연산자 ( operator ) | 연산에 사용되는 부호, 기호 |
피연산자 ( operand ) | 연산에 대상이되는 데이터 |
연산식 ( expressions ) | 피연산자와 연산자로 연산을 하는 과정 |
public void expressions() {
// primitive type 변수 선언과 초기화
int a = 1;
int b = 2;
int c = a + b;
// 연산 : 위 코드가 연산
// 연산자 : +
// 피연산자 : a, b
// 연산식 : a + b
}
산술 연산자
+, -, *, /, % 5가지로 구성되어있습니다.
마지막 %는 나머지값을 구하는 연산자로 Modulo라고 불립니다.
간단한 코드로 살펴보겠습니다.
public static void 산술연산자() {
int var1 = 1;
int var2 = 2;
System.out.println("var1 + var2 = " + (var1 + var2));
System.out.println("var1 - var2 = " + (var1 - var2));
System.out.println("var1 * var2 = " + (var1 * var2));
System.out.println("var1 / var2 = " + (var1 / var2));
System.out.println("var1 % var2 = " + (var1 % var2));
double var3 = 1;
double var4 = 2;
System.out.println("var3 / var4 = " + (var3 / var4));
}
여기서 주의깊게 살펴보아야할 것은 나누기 연산에 대한 결과값입니다.
int 자료형을 사용했을 경우는 1 / 2 는 0.5라는 결과값이 나와야하지만 int 타입은 소숫점은 표현하지 않기 때문에 .5를 절삭하고 0이라는 결과값이 나왔습니다. 반면에 double 자료형을 사용하면 0.5라는 결과를 얻을 수 있습니다.
피연산자의 자료형의 표현범위에 따라서 결과값이 다르게 나타납니다.
비트 연산자
& | AND |
| | OR |
^ | XOR |
>> | Right Shift |
<< | Left Shift |
public static void 비트연산자() {
/**
* int 자료형은 8 Byte이므로 32비트로 표현된다.
* 0000 0000 0000 0000
* 연산 설명을 편의를 위해 앞의 12자리는 제외하고 실제 값이 표현되는 마지막 4자리만 표현하겠습니다.
*/
int var1 = 3; // 0011
int var2 = 5; // 0101
System.out.println("var1 & var2 = " + (var1 & var2));
System.out.println("var1 | var2 = " + (var1 | var2));
System.out.println("var1 ^ var2 = " + (var1 ^ var2));
System.out.println("var1>> = " + (var1 >> 1));
System.out.println("var1<< = " + (var1 << 1));
}
AND ( & )
AND 연산자는 같은 위치의 값 모두 1일 경우에 값이 1이 됩니다.
결과값으로 1 (0001) 이 나옵니다.
0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 1 |
OR ( | )
OR 연산자는 같은 위치의 값 중 하나라도 1일 경우 값이 1이 됩니다.
결과값으로 7 (0001)이 나옵니다.
0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 1 |
XOR ( ^ )
XOR 연산자는 같은 위치의 값 중 한개만 1이어야 1이 됩니다.
결과값으로 6 ( 0110 )이 나옵니다.
0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 |
Right Shift ( >> )
Right Shift 연산자는 값을 오른쪽으로 shift 시킵니다.
결과값으로 1이 나옵니다.
0 | 0 | 1 | 1 |
0 | 0 | 0 | 1 |
Left Shift ( << )
Lift Shift 연산자는 값을 왼쪽으로 shift 시킵니다.
결과값으로 6이 나옵니다.
0 | 0 | 1 | 1 |
0 | 1 | 1 | 0 |
관계 연산자
관계 연산자는 양쪽에 있는 데이터를 비교하는 연산자입니다.
== | 양 쪽 데이터가 같으면 true, 다르면 false |
!= | 양 쪽 데이터가 같으면 false, 다르면 true |
> | 왼쪽 데이터가 오른쪽 데이터보다 크면 true, 작으면 false |
< | 왼쪽 데이터가 오른쪽 데이터보다 크면 false, 작으면 true |
>= | 왼쪽 데이터가 오른쪽 데이터보다 크거나 같으면 true, 작으면 false |
<= | 왼쪽 데이터가 오른쪽 데이터보다 작거나 같으면 true, 크면 false |
instanceod | 양 쪽 객체의 타입이 같으면 true, 다르면 false |
public static void 관계연산자() {
int var1 = 1;
int var2 = 4;
Account a = new Account();
System.out.println("var1 == var2");
System.out.println(var1 == var2);
System.out.println("var1 != var2");
System.out.println(var1 != var2);
System.out.println("var1 > var2");
System.out.println(var1 > var2);
System.out.println("var1 < var2");
System.out.println(var1 < var2);
System.out.println("var1 <= var2");
System.out.println(var1 <= var2);
System.out.println("var1 >= var2");
System.out.println(var1 >= var2);
System.out.println("a instanceof Account");
System.out.println(a instanceof Account);
}
instanceof는 밑에서 자세히 다루겠습니다.
논리연산자
논리연산자는 비트연산과 매우 흡사합니다. 차이점은 논리연산자의 피연산자는 boolean 타입입니다.
&& | 양쪽 데이터 모두 true인 경우 true, 하나라도 false라면 false |
|| | 양쪽 데이터 중 한 개 이상이 true면 true, 둘다 false면 false |
private static void 논리연산자() {
boolean var1 = true;
boolean var2 = true;
boolean var3 = false;
boolean var4 = false;
System.out.println("var1 && var2");
System.out.println(var1 && var2);
System.out.println("var1 && var3");
System.out.println(var1 && var3);
System.out.println("var1 || var3");
System.out.println(var1 || var3);
System.out.println("var3 || var4");
System.out.println(var3 || var4);
}
&& 연산자는 첫번째 데이터가 false라면 두번째 데이터는 확인하지 않습니다.
|| 연산자는 첫번째 데이터가 true라면 두번째 데이터는 확인하지 않습니다.
instanceof
instanceof는 왼쪽 데이터가 오른쪽 클래스와 일치하면 true입니다.
public class Test1 extends TestParent {
}
public class TestInterfaceImpl implements TestInterface {
}
private static void instanceofTest() {
Test1 test1 = new Test1(); // TestParent를 상속 받은 클래스
TestInterfaceImpl testInterfaceImpl = new TestInterfaceImpl(); // TestInterface를 implements 받은 클래스
System.out.println("test1 instanceof Test1");
System.out.println(test1 instanceof Test1);
System.out.println("test1 instanceof TestParent");
System.out.println(test1 instanceof TestParent);
System.out.println("testInterfaceImpl instanceof TestInterfaceImpl");
System.out.println(testInterfaceImpl instanceof TestInterfaceImpl);
System.out.println("TestInterfaceImpl instanceof TestInterface");
System.out.println(testInterfaceImpl instanceof TestInterface);
}
instanceof는 상속을 받은 클래스와 상속을 한 클래스도 true가 됩니다.
마찬가지로 interface와 implements 받은 클래스도 결과는 true가 됩니다.
assignment(=) operator
오른쪽의 피연산자 값을 왼쪽 피연산자에 할당합니다.
= 는 다른 연산자와 같이 쓸 수 있습니다.
private static void assignmentTest() {
int a = 8;
int b = 3;
System.out.println("a = b -> " + (a = b));
System.out.println("a += b -> " + (a += b)); // a = a + b
System.out.println("a -= b -> " + (a -= b)); // a = a - b
System.out.println("a *= b -> " + (a *= b)); // a = a * b
System.out.println("a /= b -> " + (a /= b)); // a = a / b
System.out.println("a %= b -> " + (a &= b)); // a = a & b
}
화살표 (->) 연산자
화살표 연산자는 Lamda가 나타나고 생긴 연산자 입니다. ( Java 8 시점 )
람다 표현식은 단일 메서드 인터페이스인 경우 간결하게 표현할 수 있는 방식입니다.
화살표 연산자 왼쪽에는 파라미터를 작성하고 오른쪽에는 파라미터로 수행할 로직을 블록을 설정하여 작성합니다. 만약 로직이 한 줄이라면 블록은 생략할 수 있습니다.
private static void lamdaTest() {
Test1 test1 = new Test1();
test1.addTestInterface(new TestInterface() {
@Override
public void addTestListener(Object o) {
System.out.println("add Test lister = " + o);
}
});
test1.callInterface("not use lamda");
Test1 test2 = new Test1();
test2.addTestInterface(testLister -> {
System.out.println("add Test lister lamda = " + testLister);
});
test2.callInterface("use lamda");
}
코드의 2가지 로직은 같은 기능을 수행합니다.
이처럼 람다표현식을 사용하면 소스를 간결화할 수 있습니다.
3항 연산자
자바에서는 3개의 연산자를 이용하는 조건 연산자입니다.
물음표와 콜론을 사용하는 연산자입니다.
private static void 삼항연산자() {
String a = "a";
System.out.println("a == a -> " + (a == "a" ? true : false)); // 1)
System.out.println("a == b -> " + (a == "b" ? true : false));
// 1) 과 동일하게 작동
if (a == "a") {
return ture;
} else {
return false;
}
}
{조건} ? {조건이 참인 경우 실행} : {조건이 거짓인 경우 실행}
3개의 피연산자인 경우에만 사용하는 것을 추천합니다.
아래 코드는 3항 연산자를 두 번 사용한 코드입니다. 과연 보기 편한가요???
boolean c = a == "b" ? a == "c" ? false : true : false;
연산자 우선 순위
저 같은 경우는 모든 것을 암기하지 않고 꼭 먼저 실행되어야 하는 연산은 괄호를 붙혀서 사용하고 있습니다.
java13 switch 연산자
일반적으로 사용하는 switch 문과 java12부터 추가된 multi, java13부터 추가된 arrow를 살펴보겠습니다.
private static void switchTest(String a) {
// basic switch
switch (a) {
case "a" :
System.out.println("a");
break;
case "b" :
System.out.println("b");
break;
case "c":
System.out.println("c");
break;
default:
System.out.println("default");
}
// multi switch
switch (a) {
case "a", "b":
System.out.println("a or b");
break;
case "c", "d":
System.out.println("c or d");
break;
default:
System.out.println("default");
}
// arrow switch
switch (a) {
case "a" -> System.out.println("a");
case "b" -> System.out.println("b");
case "c" -> System.out.println("c");
default:
System.out.println("defalut");
}
// expression
String result = switch (a) {
case "a" -> "TextA";
case "b" -> "TextB";
case "c" -> "TextC";
default -> "default";
}
}
위와 같이 switch 문을 사용할 수 있습니다.