본문 바로가기

Programing/JVM(Java, Kotlin)

[Java] count++, count+=1, count = count + 1 차이는

아래와 같은 반복문이 있었는데

public class ForSumFrom1To100Example {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        System.out.println("1~100 합: " + sum);
    }
}

어떤 분이 실수로 반복문에 인덱스 변수를 넣어야 할 것에 대해 숫자 1로 입력했다고 하였다.

public class ForSumFrom1To100Example {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += 1;	// 실수
        }
        System.out.println("1~100 합: " + sum);
    }
}

원래는 1부터 100까지의 합인 5050이 나와야 하는데 결과가 100이 나왔다고 한다.

왜 결과가 입력한 값의 100 배가 되었는지가 궁금했다고 한다.


결과적으로 보면 아래 실수는 0부터 값을 1씩 증가시키는 것이 되어 결국은 100이 된 것이다.

동일한 유사 자바 코드들

sum += 1;

은 아래의 코드랑 동일하다고 많이 배운다.

sum = sum + 1;

또한 원래 있던 값을 하나를 증가시키므로 아래의 코드랑 동작이 같다고 볼 수 있다.

sum++;

 

비슷해보이는 이 세 코드는 어떤 차이가 있을까?

일단 자바 언어의 세계에서는 동일한 동작을 하므로 큰 차이가 없다.

하지만 JVM에서는 두 가지 그룹으로 나누어서 생각할 수 있다.

1) sum++; 혹은 sum += 1;

2) sum = sum + 1;

 

전자의 경우에는 아래와 같은 형태로 바이트 코드로 컴파일 된다.

IINC 1 1

IINC 명령은 정수의 증가하는 명령으로 index와 상수를 받는다.

위의 명령의 경우 현재 프레임에 있는 지역 변수 배열의 1번 인덱스의 값을 상수 1만큼 증가시키라는 명령이다.

Increment local variable by constant

후자의 경우는 아래와 같은 형태로 바이트 코드로 컴파일 된다. (ILOAD 및 ISTORE의 숫자 값은 바뀔 수 있다.)

ILOAD 1
ICONST_1
IADD
ISTORE 1

지역 변수 1번 인덱스의 정수 값을 연산 스택(operand stack)에 넣고(push),

상수 1을 연산 스택에 넣고, 정수의 더하기 연산을 수행 후 다시 지역 변수 1에 넣는 것이다.

Load int from local variable
Store int into local variable

동일한 동작임에도 바이트코드가 다르게 되는 것이다.

따라서 1사이클에 할 수 있는 연산을 4사이클로 나누어서 수행해야 하는 차이가 발생한다.