Java의 정석 - 연산자

원태연·2022년 5월 30일
0

Java의 정석

목록 보기
4/19
post-thumbnail

연산자

연산자의 종류

기본적으로 있을 건 다 있고, 모르거나 헷갈릴 수 있는 내용만 살펴보자.

  • 논리 연산자 : &&, ||, !

  • 삼항 연산자: ? :

  • 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억 정도고, long2^(63)정도 될것이다.

int a = 1500000000;
int b = 1500000000;
System.out.println(a+b); //   -1294967296
// a + b 가 int의 볌위를 벗어나는 경우
// 오버플로우가 발생한다

intint의 연산은 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
  

floatdouble의 기저 차이 때문에 주의가 필요하다

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

profile
앞으로 넘어지기

0개의 댓글