여러 개의 연산자가 포함된 연산식에서의 증감 연산자
증감 연산자가 변수 앞에 있으면(++x)
=> 우선 변수를 1 증가 또는 1 감소시킨 후에 다른 연산을 수행한다.
증감 연산자가 변수 뒤에 있으면(y++)
=> 모든 연산을 끝낸 후에 변수를 1증가 또는 1 감소시킨다.
int x = 1;
int y = 1;
int result = ++x + 10;
int result2 = y++ + 10;
여기서, 3번째 줄의 진행순서는,
=> x를 1 증가 => int result1 = 2 + 10;
이 되지만,
4번째 줄의 진행순서는,
=> int result2 = 1 + 10; => y를 1 증가
가 된다.
따라서 result1과 result2 에는 각각 12와 11이 저장된다. 그리고 최종 x와 y의 값은 2가 된다.
오버플로우와 언더플로우
정수 타입 연산에서 오버플로우 또는 언더플로우가 발생되면, 실행 에러가 발생할 것 같지만,
그렇지 않고 해당 정수 타입의 최솟값 또는 최댓값으로 되돌아간다.
예를 들어 byte 타입일 경우, 최댓값 127에서 1을 더하면 128이 되어 오버플로우가 발생, 연산결과는 최솟값인 -128이 된다.
byte value = 127;
value++; // 1더함
System.out.println(value); //-128
마찬가지로, -128에서 1을 빼면 언더플로우가 발생해, 127이 됨.
byte value = -128;
value--; // 1뺌
System.out.println(value); // 127
연산 과정 중에 발생하는 오버플로우/언더플로우는 우리가 기대하는 값이 아니므로, 해당 타입 범위 내에서 연산이 수행되도록 신경 쓰기.
정확한 계산은 정수 연산으로
다음 코드는 사과 1개를 0.1 단위의 10조각으로 보고, 그중 7조각(0.7)을 뺀 3조각(0.3)을 result 변수에 저장한다.
public class AccuracyExample {
public static void main(String[] args) {
int apple = 1;
double pieceUnit = 0.1;
int number = 7;
double result = apple - number*pieceUnit;
System.out.println("사과 1개에서 남은 양: " + result);
}
}
//실행 결과
//사과 1개에서 남은 양: 0.29999999999999993
이런 식으로, 정확히 0.3이 되지 않는다.
이것은 부동 소수점 방식을 사용하는 실수 타입에서 흔히 일어난다. 그렇게 때문에 정확한 계산이 필요하면, 정수 연산으로 변경해서,
public class AccuracyExample {
public static void main(String[] args) {
int apple = 1;
int totalpieces = apple * 10;
int number = 7;
int result = totalPieces - number;
System.out.println("10조각에서 남은 조각: " + result);
System.out.println("사과 1개에서 남은 양: " + result/10.0);
}
}
//실행 결과
//10조각에서 남은 조각: 3
//사과 1개에서 남은 양: 0.3
이렇게 처리하자.
비교 연산자
피연산자의 타입이 다를 경우에는 비교 연산을 수행하기 전에 타입을 일치시킨다.
ex) 'A' == 65는 'A'가 int 타입으로 변환되어 65가 된 다음, 65 == 65로 비교한다.
ex) 3 =3.0 은 3을 double 타입인 3.0으로 변환한 다음 3.0 == 3.0으로 비교한다.
But,
한 가지 예외가 있는데,
0.1f == 0.1에서 0.1f가 double 타입으로 변환되면 0.1 == 0.1이 되어 true가 산출되어야 하지만,
이 결괏값은 false가 산출된다.
그 이유는, 부동 소수점 방식을 사용하는 실수 타입은 0.1을 정확히 표현할 수 없을 뿐만 아니라 float타입과 double 타입의 정밀도 차이
때문이다.
해결책은 다음과 같이 피연산자를 float 타입으로 강제 타입 변환 후에 비교 연산을 하면 된다.
0.1f == (float)0.1 // true
문자열을 비교할 때는 동등(==,!=) 연산자 대신 equals()와! equals()를 사용한다.
동등 연산자는 두 개의 문자열이 메모리 내의 같은 위치를 참조하는지를 확인하기에,
문자상으론 같아도, 다른 객체면 false를 뱉기 때문에,
문자 자체만 비교하고 싶다면 equals()와 !equals()를 사용한다.
boolean result = str1.equals(str2);
boolean result = !str1.equals(str2);
switch 문
괄호 안의 변숫값에 따라 해당 case로 가서 실행문을 실행시킴.
public class SwitchExample {
public static void main(String[] args) {
int num = 4;
switch(num) {
case 1:
System.out.println("1번입니다.");
break;
case 2:
System.out.println("2번입니다.");
break;
case 3:
System.out.println("3번입니다.");
break;
case 4:
System.out.println("4번입니다.");
break;
case 5:
System.out.println("5번입니다.");
break;
default:
System.out.println("안녕");
}
}
}
//실행 결과
//4번입니다.
case 끝에 있는 break는 다음 case를 실행하지 않고 switch문을 빠져나가기 위해 필요하다.
case를 다 거친 후, 아무 case도 해당되지 않을 때는 default에 해당되는 내용이 실행된다. else와 비슷함
switch문의 괄호에는 정수 타입(byte, char, short, int, long)과 문자열 타입(String) 변수를 사용해서 switch-case문을 돌릴 수 있다.
Java 12 이후부터는, swtich 문에서 Expressions를 사용할 수 있다.
break 문을 없애는 대신, 화살표와 중괄호를 사용해 가독성이 좋아졌다.
public class SwitchExpressionsExample {
public static void main(String[] args) {
char grade = "B";
switch(grade) {
case 'A','a' -> {
System.out.println("우수 회원입니다.");
}
case 'B','b' -> {
System.out.println("우수 회원입니다.");
}
default -> {
System.out.println("손님입니다.");
}
}
switch(grade) {
case 'A', 'a' -> System.out.println("우수 회원입니다.");
case 'B', 'b' -> System.out.println("일반 회원입니다.");
default -> System.out.println("손님입니다.");
} // 중괄호 안에 실행문 하나만 있으면 중괄호 생략 가능
}
}
//실행 결과
//일반 회원입니다.
//일반 회원입니다.
do-while 문
do-while 문은 조건식에 의해 반복 실행한다는 점에서는 while 문과 동일하다.
while 문은 시작할 때부터 조건식을 평가하여 블록 내부를 실행할지 결정하지만,
경우에 따라서는 블록 내부를 먼저 실행시키고, 실행 결과에 따라서 반복여부를 결정하는 경우도 있다.
=> 이때 do-while 문을 사용한다.
do{
//(1)실행문 // 반복 영역
} while ( (2)조건식 ); // 조건식이 true일 경우, 실행문으로 돌아감
ex) "입력받은(do) 값이? 가 아니라면(while) 반복"인 상황에서 do-while 문을 사용함.
'Java' 카테고리의 다른 글
[Java] Enum 정의 + 사용법 + 예제 (0) | 2023.09.04 |
---|---|
[Java] 인터페이스 (0) | 2023.08.09 |