" 자바가 제공하는 다양한 연산자를 학습하세요. "
수학적 계산에 사용되는 연산자. 두 개의 피연산자를 가지는 이항 연산자.
산술 연산자 | 설명 |
---|---|
+ | 더하기 |
- | 빼기 |
* | 곱하기 |
/ | 나누기 |
% | 나머지 |
public class ArithmeticOperator {
public static void main(String[] args) {
int result = 1 + 2;
System.out.println("1 + 2 = " + result); // 결과: 3
int original_result = result;
result = result - 1;
System.out.println(original_result + " - 1 = " + result); // 결과: 2
original_result = result;
result = result * 2;
System.out.println(original_result + " * 2 = " + result); // 결과: 4
original_result = result;
result = result / 2;
System.out.println(original_result + " / 2 = " + result); // 결과: 2
original_result = result;
result = result + 8;
System.out.println(original_result + " + 8 = " + result); // 결과: 10
original_result = result;
result = result % 7;
System.out.println(original_result + " % 7 = " + result); // 결과: 3
original_result = result;
}
}
단항 연산자 | 설명 |
---|---|
+ | 양수 |
- | 음수 |
++ | 1 증가 |
-- | 1 감소 |
! | 반대(논리 연산자) |
public class UnaryOperator {
public static void main(String[] args) {
int result = +1;
System.out.println(result); // 결과: 1
result--;
System.out.println(result); // 결과: 0
result++;
System.out.println(result); // 결과: 1
result = -result;
System.out.println(result); // 결과: -1
boolean success = false;
System.out.println(success); // false
System.out.println(!success); // true
}
}
비트(bit) 단위로 논리 연산을 할 때 사용하는 연산자
비트 연산자 | 설명 |
---|---|
& | 대응되는 비트가 모두 1이면 1을 반환(비트 AND 연산) |
| | 대응되는 비트 중에서 하나라도 1이면 1을 반환(비트 OR 연산) |
^ | 대응되는 비트가 서로 다르면 1을 반환(비트 XOR 연산) |
~ | 비트를 1이면 0, 0이면 1로 반전(비트 NOT 연산, 1의 보수) |
<< | 명시된 수만큼 비트들을 모두 왼쪽으로 이동(left shift 연산) |
>> | 부호를 유지하고 지정된 수만큼 모두 오른쪽으로 이동(right shift 연산) |
>>> | 명시된 수만큼 비트들을 모두 오른쪽으로 이동, 새로운 비트는 0으로 채움(unsigned right shift 연산) |
// 비트 NOT 연산(보수 연산)
byte b = ~12; // ~00001100
System.out.println(b); // 결과: -13
System.out.println(String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'));
// 결과: 00000100
byte flags = 12; // 00001100
byte f = 8; // 00001000
flags = (byte) (flags & ~f); // 00001100 & ~00001000
System.out.println(String.format("%8s", Integer.toBinaryString(flags & 0xFF)).repalce(' ', '0'));
// 00000100
// 비트 AND 연산
10 & 7 // 00001010 & 00000111 → 00000010
if((flags & f) != 0) // 플래그 값들 중에서 특정 플래그 값 f가 의도대로 세팅되어 있는지 확인.
// 비트 OR 연산
10 | 7 // 00001010 | 00000111 → 00001111
flags = flags | f; // 플래그 값들 중에서 특정 플래그 값 f를 세팅(f 플래그값 위치에 1이 있음)
// 비트 XOR 연산
10 ^ 7 // 00001010 ^ 00000111 → 00001101
// left shift(<<)
10 << 1 // 0b00001010 << 1 = 00010100 = 20 = 10*2
7 << 3 // 0b00000111 << 3 = 00111000 = 56 = 7*8
-1 << 2 // 0xFFFFFFFF << 2 = 0xFFFFFC = -4 = -1*4
// right shift(>>)
10 >> 1 // 00001010 >> 1 = 00000101 = 5 = 10/2
27 >> 3 // 00011011 >> 3 = 00000011 = 3 = 27/8
-50 >> 2 // 11001110 >> 2 = 11110011 = -13 != -50/4
// unsigned right shift(>>>)
0xff >>> 4 // 11111111 >>> 4 = 00001111 = 15 = 255/16
-50 >>> 2 // 0xFFFFFFCE >>> 2 = 0x3FFFFFF3 = 1073741811
두 피연산자의 상대적인 크기를 판단하는 연산자. 왼쪽의 피연산자와 오른쪽의 피연산자를 비교하여, 어느 쪽이 더 큰지, 작은지, 또는 서로 같은지를 판단. 결합방향은 왼쪽에서 오른쪽
관계 연산자 | 설명 |
---|---|
== | 같으면 true |
!= | 다르면 true |
> | 왼쪽이 크면 true |
>= | 왼쪽이 오른쪽보다 크거나 같으면 true |
< | 오른쪽이 크면 true |
<= | 오른쪽이 왼쪽보다 크거나 같으면 true |
char c1 = 'a', ch2 = 'A';
System.out.println(ch1 == ch2); // false
System.out.println(ch1 > ch2); // true
논리적으로 true와 false를 판단
논리 연산자 | 설명 |
---|---|
&& | 논리식이 모두 참이면 true(논리 AND 연산) |
|| | 논리식 중에 하나라도 참이면 true(논리 OR 연산) |
! | 논리식이 true이면 false, false이면 true(논리 NOT 연산) |
^ | 논리식이 서로 다를 때 true(논리 XOR 연산) |
public class LogicalOperator {
public static void main(String[] args) {
System.out.println('a' > 'b'); // false
System.out.println(3 >= 2); // true
System.out.println(-1 < 0); // true
System.out.println(3.45 <= 2); // false
System.out.println(3 == 2); // false
System.out.println(3 != 2); // true
System.out.println(!(3 != 2)); // false
System.out.println((3 > 2) && (3 > 4)); // false
System.out.println((3 != 2) || (-1 > 0)); // true
System.out.println((3 != 2) ^ (-1 > 0)); // true
}
}
참조 변수가 참조하고 있는 인스턴스의 실제 타입을 반환.
해당 객체가 어떤 클래스(부모 클래스 포함)나 인터페이스로부터 생성되었는지 판별
public class InstanceofEx {
public static void main(String[] args) {
Parent obj1 = new Parent();
Parent obj2 = new Child();
System.out.println("obj1 instanceof Parent: " + (obj1 instanceof Parent));
System.out.println("obj1 instanceof Child: " + (obj1 instanceof Child));
System.out.println("obj1 instanceof MyInterface: " + (obj1 instanceof MyInterface));
System.out.println("obj2 instanceof Parent: " + (obj2 instanceof Parent));
System.out.println("obj2 instanceof Child: " + (obj2 instanceof Child));
System.out.println("obj2 instanceof MyInterface: " + (obj2 instanceof MyInterface));
}
}
class Parent {}
class Child extends Parent implements MyInterface {}
interface MyInterface {}
// 결과
obj1 instanceof Parent: true
obj1 instanceof Child: false
obj1 instanceof MyInterface: false
obj2 instanceof Parent: true
obj2 instanceof Child: true
obj2 instanceof MyInterface: true
int a = 0;
int b = 0;
int c = 1;
Player Ronaldo = new Player("Cristiano Ronaldo", "Portugal", "JuventusFC", "FW", "187", "83.5", "19850205");
Player Messi = new Player("Lionel Messi", "Argentina", "FCBarcelona", "FW", "170", "72", "19870624");
i += 2; // i를 2 증가해서 저장
c -= 5; // c를 5 감소해서 저장
flags |= f; // 플래그 값들 중에서 특정 플래그 값 f를 세팅해서(비트 OR 연산) flags 저장
flags &= ~f; // 플래그 값들 중에서 특정 플래그 값 f를 세팅하지 않도록(f의 보수로 비트 AND 연산) flags 저장
// (인자, ...) -> { /* 메소드 바디 */ }
// 두 개의 숫자 더하기
public interface Compare {
public int compareTo(int a, int b);
}
public static void exec(Compare compare) {
int k = 10;
int m = 20;
int value = compare.compareTo(k, m);
System.out.println(value);
}
public static void main(String[] args) {
exec((i, j) -> { // compareTo(int a, int b) 부분, Compare 인터페이스를 구현
return i + j;
});
}
// 두 개의 숫자 중 큰 수 출력하기
@FunctionalInterface
public interface MyNumber {
int getMax(int num1, int num2);
}
public static void main(String[] args) {
MyNumber max = (x, y) -> (x >= y) ? x : y;
System.out.println(max.getMax(10, 30));
}
// Runnable 인스턴스 생성
Runnable runnable = ()->{
for(int i = 0; i < 30; i++) {
System.out.println(i);
}
};
Thread thread = new Thread(runnable);
thread.start();
// Thread 생성
Thread thread = new Thread(()-> {
for(int i = 0; i < 10; i++) {
System.out.println(i);
}
});
thread.start();
// <조건> ? <true일 경우 반환되는 값> : <false일 경우 반환되는 값>
x > y ? x : y
// 두 번째와 세 번째 연산자는 같은 타입으로 변환할 수 있어야 함.
int completedChapter = 3;
System.out.println((completedChapter >= 14) ? "티셔츠" : "공부해");
// 출처: 명품 Java Programming
아래와 같은 switch 문이 있을 때,
public enum Day { SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; }
// ...
int numLetters = 0;
Day day = Day.WEDNESDAY;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new IllegalStateException("Invalid day: " + day);
}
System.out.println(numLetters);
Java 12부터는 콜론(:)대신 화살표 연산자(->)를 사용할 수 있다.
int numLetters = 0;
Day day = Day.WEDNESDAY;
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> numLetters = 6;
case TUESDAY -> numLetters = 7;
case THURSDAY, SATURDAY -> numLetters = 8;
case WEDNESDAY -> numLetters = 9;
default -> throw new IllegalStateException("Invalid day: " + day);
};
System.out.println(numLetters);
Java 13부터는 break 대신 yield를 사용한다.
Day day = Day.WEDNESDAY;
int numLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
yield 6;
case TUESDAY:
System.out.println(7);
yield 7;
case THURSDAY:
case SATURDAY:
System.out.println(8);
yield 8;
case WEDNESDAY:
System.out.println(9);
yield 9;
default:
throw new IllegalStateException("Invalid day: " + day);
};
System.out.println(numLetters);
위에서는 콜론이 있는 구문에서 yield가 빠지면, 런타임 에러가 발생한다. 하지만 아래와 같이 화살표 연산자를 사용할 경우에는 yield가 빠지면, 컴파일 에러가 발생하여 미리 알 수 있기 때문에 화살표 연산자를 사용할 것을 권장한다.
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> {
System.out.println(6);
yield 6;
}
case TUESDAY -> {
System.out.println(7);
yield 7;
}
case THURSDAY, SATURDAY -> {
System.out.println(8);
yield 8;
}
case WEDNESDAY -> {
System.out.println(9);
yield 9;
}
default -> {
throw new IllegalStateException("Invalid day: " + day);
}
};