기본적으로 있을 건 다 있고, 모르거나 헷갈릴 수 있는 내용만 살펴보자.
논리 연산자 : &&
, ||
, !
삼항 연산자: ? :
instanceof
: 객체 타입을 확인 할 때 씀
Obj a = new Obj();
System.out.println(a instanceof Obj); //True
비트 연산자는 다음에...
다른 타입끼리 더하거나 빼는 등 산술 연산이 실행될때, 명시하지 않으면 자동 형변환이 진행된다는 것을 살펴보았다.
하지만, JVM의 피연산자 스택은 피연산자를 4byte단위로 저장하기 때문에 4byte이하, 혹은 이상의 데이터타입을 연산할 경우 4byte단위로 변환하는 과정이 필요하다.
그래서 short a = 1;
byte b = 1;
일때, a+b
의 경우는int + int
형으로 계산된다.
사용하는 메모리 보단 Java의 성능을 높히고 싶다면, 작은 숫자더라도 int
로 계산하는것이 좋을 것이다.
int a = 5;
int b = 2;
// 원하는 값
// a / b = 2.5
// (int) / (int) = (int)
// 5 / 2 = 2
//Solution
// (int) / (float) = (float)2.5
// a / (float)b = 2.5
위와 같은 경우도 발생할 수 있으니, 산술 변환을 잘 활용하여 원하는 값을 얻어낼 수 있도록 하자.
int
의 범위는 -2^(31) ~ 2^(31)
으로 최대값이 대략 20억 정도고, long
은 2^(63)
정도 될것이다.
int a = 1500000000;
int b = 1500000000;
System.out.println(a+b); // -1294967296
// a + b 가 int의 볌위를 벗어나는 경우
// 오버플로우가 발생한다
int
와 int
의 연산은 int
이고, 연산 결과가 int
의 범위를 넘어서 오버플로우가 발생하였다.
이처럼, 저장할 수 있는 비트를 넘어버리면 오버플로우가 발생한다.
만약 int의 최대값을 넘어서 오버플로우가 발생했다면, int의 최솟값으로 바뀔것이다.
intMax + 1 = intMin
이다. TV채널을 올리다가 끝 번호까지 올라가면, 다시 제일 낮은 번호의 채널로 돌아가는 것과 비슷하다.
오버 플로우를 인식하고 데이터 형변환을 활용하여 계산결과로부터 원하는 정보를 얻어 낼 수 있도록 하자.
'a'의 코드값은 97이고, 'b'의 코드값이 98, 'c'의 코드값이 99일 때,
char c1 = 'a'; //a
char c2 = c1; //a
int i = c1 + 1; //'a' + '1'이 아니라, int로 바뀐다 (문자열의 경우는 전자이다)
char c3 = (char)(c1 + 1);
//char c3 = c1 + 1; //컴파일 에러 => 계산결과가 ic1 + 1이기 때문에 char의 타입과 맞지 않다
c2++;
System.out.println(c1); // 'a'
System.out.println(c2); // 'b'
System.out.println(c3); // 'b'
System.out.println(i); // 98
정수와의 연산을 통해 원하는 문자에 접근할 수 있다.
65 ~ 65+25
, 소문자 알파벳은 97 ~ 97 +25
i++
: 값이 참조된 후에 증가++i
: 값이 참조되기 전에 증가int i = 5;
int j = 0;
j = i++;
System.out.println(j); // 5
i = 5;
j = 0;
j = ++i;
System.out.println(j); // 6
크게 다를 건 없지만, 산술연산처럼 다른 타입의 데이터를 비교하는 경우를 살펴 볼 필요가 있다.
10 == 10.0f; //true
//10이 float으로 형변환
'0' == 0 ; //false
//'0'은 코드로 48
'A' == 65 ; //true
'A' > 'B' ; //false
// 65 > 66 false
'A'+1 != 'B' ; //false
float
과 double
의 기저 차이 때문에 주의가 필요하다
10.0 == 10.0f; //true
0.1 == 0.1f; //false
//float의 0.1 은 0.10000000????~이기 때문에 0.100000000000000...과 다르다.
float f = 0.1;
double d = 0.1;
double d2 = (double)f;
d == f; //false
d == d2; //false
d2 == f; //true
d = Math.round(d);
d2 = Math.round(d2);
d == d2; //true
실수간의 유의미한 비교를 위해선 round()나 버림을 통해 정확한 값을 결정한뒤 비교하는 것이 좋다.
문자열의 비교도 비슷하게 할 수 있지만 equals()
를 활용하여 비교할 수 있다. 단, 비교연산자와의 차이점은 객체가 달라도 값이 같으면 같다고 표기한다. 좀 더 느슨한 비교라고 할 수 있다.
String str1 = "abc";
String str2 = new String("abc");
"abc" == "abc" ; //true
str2 == "abc" ; //false (객체가 다름)
str2.equals("abc"); //true (값만 비교)
str2.equalsIgnoreCase("ABC"); // true
//equalsIgnoreCase()은 대소문자가 무시된 채로 값을 비교
&&
, ||
!
이 있다.
논리연산이 2개 이상일 경우, 앞에서부터 연산한다는 점을 활용할 수 있다.
int a = 10;
int b = 30;
a < 20 and b < 20; //a < 20이 참이기 때문에 b < 20을 연산
b < 20 and a < 20; //b < 20이 거짓이지 때문에 바로 false 반환, a < 20은 연산 X
조건1 ? 참 : 거짓
i += 3
<==> i = i + 3