연산자
대표적인 연산자로 다음 4 연산자가 있다.
산술 연산자 * / + -
비교(관계) 연산자 > < <= >= == !=
논리 연산자 && ||
대입 연산자(assignment operator) =
특수한 형태의 연산자는 추후에 다루자
전위/후위 단항 연산자
전에 많이 써봐서 간단하다.
i++ : 값이 참조되기 전에 증가시킨다 |
++i : 값이 참조된 후에 증가시킨다. |
public class javaVar {
public static void main(String[] args) {
int i = 3;
System.out.println(i++); // 참조된 후에 덧셈이 되므로 그대로 3 출력
i = 3;
System.out.println(++i); // 참조되기 전에 덧셈이 되므로 4 출력
}
}
만약 이해하기 어렵다면 전위형(++i)은 다른 조작 전에 우선 실행되며 후위형(i++)은 조작 후에 이뤄진다고 생각하자
산술 연산자
기본 내용은 생략합니다.
문제는 다음과 같이 타입에서 나타난다. 둘 다 int이기 때문에 반환하는 값도 int가 된다.
int a = 3;
int b = 4;
System.out.println(b / a); // 1.333333 이 아니라 1
타입 프로모션을 이용하려면 어느 한 쪽을 float이나 double로 바꿔야 한다. float은 소수점 6자리 까지 정확도를 보증하는 것을 잊지말자
float a = 3f;
int b = 4;
System.out.println(b / a); // 1.3333334
나눗셈, 나머지 연산에는 무조건 float, double 자료형을 사용한다고 보는게 편합니다.
float a = 10.0f / 3.0f;
float b = 10 / 3;
System.out.println(a); // 3.3333333
System.out.println(b); // 3.0
int 0 으로 나누면 에러가 나지만 float, double으로 나누면 infinity가 나옵니다.
System.out.println(3/0); // error
System.out.println(3/0.0); // infinity
비교(관계) 연산자, 논리 연산자
기본 내용은 생략합니다.
연산의 특성 중에 Short-Circuit Evaluation(Lazy Evaluation) 이라는 것이 있다.(이하 SCE)
SCE를 간단히 설명하면, "연산의 효율 및 속도를 높이기 위해 불필요한 연산을 생략하는 행위" 이다.
쉽게 말해 True || .... 이런 꼴이 있다면 그 이후를 연산하는 것은 무의미하다. 어차피 논리적으로 True이기 때문이다. 따라서 이후는 연산하지 않는다. 이는 javascript에서도 동일하다.
저는 true && ... 꼴로 작성해서 true일 경우에만 ... 로직을 실행하게 만드는 식의 트릭을 종종 사용합니다.
public class javaVar {
public static void main(String[] args) {
int n1 = 0;
int n2 = 0;
boolean result;
result = ((n1 += 10) < 0) && ((n2 += 10) > 0); // 이미 false && 꼴이라서 이후 연산 안 함
System.out.println("result: " + result + ", n1:" + n1 + ", n2:" + n2);
result = ((n1 += 10) > 0) || ((n2 += 10) > 0); // 이미 true || 꼴이라서 이후 연산 안 함
System.out.println("result: " + result + ", n1:" + n1 + ", n2:" + n2);
}
}
== 연산자는 단순히 값이 아니라 메모리 주소가 같은지 확인합니다. 때문에 reference 타입 비교에서는 의도대로 동작하지 않고, 값을 비교하기 위해서는 equals 메서드를 사용해야 한다는 점을 기억해둡시다. 사실 deepcopy할 때도 그렇고 primitive/reference 타입 차이를 이해하는 건 기본이죠.
String s1 = new String("HELLO");
String s2 = new String("HELLO");
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
- Both s1 and s2 refers to different objects.
- When we use == operator for s1 and s2 comparison then the result is false as both have different addresses in memory.
- Using equals, the result is true because its only comparing the values given in s1 and s2.
대입 연산자(assignment operator) =
복합 대입 연산자.
사실 기존에도 많이 써온 내용이지만 비트 연산자에 대입 연산을 같이 쓰는 경우는 별로 없었다.
a += b | a = a + b |
a -= b | a = a - b |
a *= b | a = a * b |
a /= b | a = a / b |
a %= b | a = a % b |
a &= b | a = a & b |
a ^= b | a = a ^ b |
a <<= b | a = a << b |
a >>>= b | a = a >>> b |
int n1 = 0;
n1 += 3;
System.out.println(n1); // output : 3
여기서 대항연산자는 자동 형변환을 해준다.
int n1 = 0;
n1 += 15L; // n1 long타입이 됨
비트 연산자
python으로 다뤄본 적이 있으니 다음 포스트 참고 darrengwon.tistory.com/863
비트 연산자는 각각의 비트를 대상으로 연산을 진행하는 연산자이며 피연산자는 반드시 정수여야 한다.
실수를 대상으로 하는 비트 연산은 의미가 없기에 자바는 이를 지원하지 않는다.
연산자설명
& | 비트 단위로 AND 연산을 한다 |
| | 비트 단위로 OR 연산을 한다 |
^ | 비트 단위로 XOR 연산을 한다 |
~ | 피연산자의 모든 비트를 반전시켜서 얻은 결과를 반환한다 |
비트 쉬프트 연산자가 조금 더 중요하다.
비트를 왼쪽 혹은 오른쪽으로 1칸씩 움직이는 것
<< | 피연산자의 비트 열을 왼쪽으로 이동. 이동에 따른 빈 공간은 0으로 채움 |
>> | 피연산자의 비트 열을 오른쪽으로 이동. 이동에 따른 빈 공간은 음수의 경우 1, 양수의 경우 0으로 채움 |
>>> | 피연산자의 비트 열을 오른쪽으로 이동. 이동에 따른 빈 공간은 0으로 채움 |
int a = 7;
System.out.println(Integer.toBinaryString(a)); // 7은 111이다
System.out.println(a >> 1); // 오른쪽으로 한칸씩. 011이 되어서 3이 됩니다.
System.out.println(a << 1); // 왼쪽으로 한칸씩. 1110이 되어서 14가 됩니다.
instanceof
쉽게 말해 클래스의 인스턴스이냐 아니냐를 묻는 겁니다. 바로 코드로 보시죠. 직관적으로 이해가 가능합니다.
- == 객체의 메모리 주소의 비교
- instanceof 해당 클래스의 인스턴스인가?
- instanceof 연산자는 주로 조건문에서 객체가 형변환 가능한 타입인지 확인할 때 많이 사용한다.
class Test {
...
}
class Test2 extends Test{
...
}
class Operator{
public static void main(String[] args) {
Test obj1 = new Test();
Test obj2 = new Test2();
System.out.println(obj1 instanceof Test); // true
System.out.println(obj1 instanceof Test2); // false
System.out.println(obj2 instanceof Test); // true, 상속 관계
System.out.println(obj2 instanceof Test2); // true
System.out.println(null instanceof Object); // false
}
}
삼항 연산자
생략. js에서랑 같음.
int a = 3;
String output = a > 3 ? "over 3" : "nono";
System.out.println(output);
화살표 연산자
우리가 생각하는 () => ... 꼴 함수다. js에서 => 를 사용했듯 java에서는 -> 를 사용한다.
(매개변수들) -> {함수 구현}
public class thread {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("스레드 생성");
}
}).start();
new Thread(() -> {
System.out.println("람다 표현식을 사용한 스레드 생성");
}).start();
}
}
연산자의 우선순위
일반 사칙 연산에서는 *, / 가 우선되고 +, -가 나중에 계산되는 우선순위가 있다. 일반 수학에서 사용되는 법칙이 마찬가지로 적용된다.
int output = 3 + 2 * 3;
System.out.println(output);
연산자에 대한 우선순위가 정해져 있다. 산술 > 비교 > 논리 > 대입 순인데 이런 순서를 외우는 것보다 대부분 상식선에서 해결 가능한 부분이므로 참고만 하고 넘어가도록하자.
[], ., () | 1 |
expr++, expr-- | 2 |
++expr, --expr, +expr, -expr, ~, !, (type) | 3 |
*, /, % | 4 |
+, - | 5 |
<<, >>, >>> | 6 |
<, >, <=, >=, instanceof | 7 |
==, != | 8 |
& | 9 |
^ | 10 |
| | 11 |
&& | 12 |
|| | 13 |
? expr : expr | 14 |
=, +=, -=, *=, /=, %=, ^=, |=, <<=, >>=, >>>= | 15 |
참고한 글)
github.com/yeo311/java-study-with-whiteship/tree/main/week3
www.notion.so/3-f3a94e0092664d8aa1debe7e88dec43b
'Programming Language > ☕ Java' 카테고리의 다른 글
클래스 (0) | 2021.04.13 |
---|---|
변수 타입, 상수(final), 리터럴, 출력 지시자, 타입 캐스팅 (0) | 2020.11.15 |
제어문 : 조건문(if/switch)과 반복문(for/while) (0) | 2020.09.12 |
IDE없이 직접 컴파일하고 실행해보기 (0) | 2020.09.12 |
openJDK 설치, JVM, JIT 컴파일 방식, hello world (0) | 2020.09.11 |