강의로 돌아가기
SHINDongHyeo

자바 10, 11, 12 에러

각각의 패턴이 얼마나 많은 문제를 맞췄는지 표현하는 변수 result1, result2, result3를
Integer로 선언했을 때는 테스트케이스 10, 11, 12번이 실패하고
int로 선언했을 때는 테스트케이스 10, 11, 12번 모두 정답처리됩니다.
무슨 차이인가요?

작성중인 코드―Solution.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import java.util.ArrayList;


public class Solution {

    public ArrayList<Integer> solution(int[] answers) {
        ArrayList<Integer> answer = new ArrayList<Integer>();

        int l = answers.length;
        int forCount = 0;
        int forPlus = 0;
        int result1 = 0;
        int result2 = 0;
        int result3 = 0;
        Integer[] pattern1 = { 1, 2, 3, 4, 5 };
        Integer[] pattern2 = { 2, 1, 2, 3, 2, 4, 2, 5 };
        Integer[] pattern3 = { 3, 3, 1, 1, 2, 2, 4, 4, 5, 5 };
        ArrayList<Integer> answers1 = new ArrayList<Integer>();
        ArrayList<Integer> answers2 = new ArrayList<Integer>();
        ArrayList<Integer> answers3 = new ArrayList<Integer>();

        int pattern1Length = pattern1.length;
        forCount = l / pattern1Length;
        forPlus = l % pattern1Length;
        for (int i = 0; i < forCount; ++i) {
            for (Integer oneAnswer : pattern1) {
                answers1.add(oneAnswer);
            }
        }
        for (int i = 0; i < forPlus; ++i) {
            answers1.add(pattern1[i]);
        }

        int pattern2Length = pattern2.length;
        forCount = l / pattern2Length;
        forPlus = l % pattern2Length;
        for (int i = 0; i < forCount; ++i) {
            for (Integer oneAnswer : pattern2) {
                answers2.add(oneAnswer);
            }
        }
        for (int i = 0; i < forPlus; ++i) {
            answers2.add(pattern2[i]);
        }

        int pattern3Length = pattern3.length;
        forCount = l / pattern3Length;
        forPlus = l % pattern3Length;
        for (int i = 0; i < forCount; ++i) {
            for (Integer oneAnswer : pattern3) {
                answers3.add(oneAnswer);
            }
        }
        for (int i = 0; i < forPlus; ++i) {
            answers3.add(pattern3[i]);
        }

        for (int i = 0; i < l; ++i) {
            if (answers[i] == answers1.get(i)) {
                result1 += 1;
            }
        }
        for (int i = 0; i < l; ++i) {
            if (answers[i] == answers2.get(i)) {
                result2 += 1;
            }
        }
        for (int i = 0; i < l; ++i) {
            if (answers[i] == answers3.get(i)) {
                result3 += 1;
            }
        }

        Integer maxResult = 0;
        if (result1 > maxResult){
            maxResult=result1;
        }
        if (result2 > maxResult){
            maxResult=result2;
        }
        if (result3 > maxResult){
            maxResult=result3;
        }


        if (result1 == maxResult){
            answer.add(1);
        }
        if (result2 == maxResult){
            answer.add(2);
        }
        if (result3 == maxResult){
            answer.add(3);
        }


        return answer;
    }

}
1 개의 답변
SHINDongHyeo

글쓴이입니다. 10, 11, 12번 케이스가 실패하신 분들은 이 부분 참고해보시면 좋을 것 같습니다.

알아보니 Integer객체 간 비교에 >나 <같은 비교 연산자는 사용이 가능하지만, 동등 연산자인 == 은 Integer객체의 주소값을 비교하게 되어 문제가 생겼습니다.
Integer객체 간 비교를 할 때 Integer객체가 가지고 있는 값에 대한 비교를 하기 위해서는 equals메서드를 사용해야 합니다.

+이때 궁금할 수 있는 부분

그럼 equals메서드를 사용하지 않고, == 연산자를 사용했음에도 불구하고 대부분의 테스트케이스는 어떻게 통과했는가?
Integer에는 -128~127까지는 캐시를 이용해 자동으로 같은 주소를 참조하게 하는 IntegerCache라는 클래스가 선언되어 있습니다.
ex) 127 이하의 자연수(100)
Integer a = 100;
Integer b= 100;

다음과 같이 a, b변수를 선언 및 초기화하면 IntegerCache로 인해 b변수를 선언하고 초기화할 때 -128~127 사이의 수 중 이미 존재하는 객체가 있는지 없는지 확인하고, 있을 경우 그 객체에 b를 연결만 시켜줌을 통해 같은 값을 지닌 중복 객체 생성을 생략합니다. 즉, 100에 대한 객체는 이미 a를 초기화할 때 생겼으므로 b는 a와 같은 객체를 참조하기만 하게 된 것입니다. 결과적으로 a와 b는 같은 객체를 참조해 객체의 값 100과 객체의 주소값을 모두 공유하게 됩니다. 그래서 이 경우에는 객체의 값을 비교하는 equals메서드와 객체의 주소값을 비교하는 ==동등연산자가 같은 결과를 반환하게 됩니다.

ex) 128 이상의 자연수(128)
Integer a = 128;
Integer b= 128;

다음의 경우에는 a를 초기화할 때 분명히 128값의 객체를 생성했음에도 불구하고 128이 IntegerCache의 범위 밖(-128~127)이여서 b를 초기화할 때는 새로운 128값의 객체를 또 만들게 됩니다. 이 경우에는 a와 b가 참조하는 객체들의 값은 128로 같지만, 참조하고 있는 객체 자체는 달라서(주소값이 다름. a와 b는 그저 같은 값을 가진 서로 다른 객체들을 참조하는 중) equals메서드를 사용하면 a와 b는 같다고 반환하지만, 동등연산자 == 을 이용해 비교하면 a와 b는 같지 않다라는 결과를 반환합니다.

정리

각 패턴별 정답횟수가 127 이하인 경우는 IntegerCache를 통해 같은 주소값을 공유해 == 동등연산자로 비교해도 equals메서드와 같은 결과를 얻었지만, 패턴별 정답횟수가 128 이상인 경우는 IntegerCache의 영향을 받지 않아 같은 정답횟수를 가져도 == 동등연산자로 비교하면 equals메서드와 다른 결과를 얻어 문제가 발생한 것입니다.

추가

ex) 강제로 IntegerCache를 사용하지 않는 경우
Integer a = 100;
Integer b= new Integer(100);
다음과 같이 IntegerCache 범위 안의 숫자라도, 강제로 b에 대한 새로운 객체를 만든다면, a와 b가 참조하는 객체는 서로 다른 객체가 될 것입니다.( 객체의 값은 100으로 동일, 객체 주소값만 다름)

  • muscleleg

    귀중한 시간내주신 훌륭한 설명 감사합니다. 덕분에 뭐가 문젠지 멘붕이었는데 해결했습니다. 감사합니다!

    muscleleg―2022.09.02 15:00
  • 조정훈

    Kia... 선생님

    조정훈―2022.12.13 15:03
  • 콘서타54

    배워갑니다..

    콘서타54―2024.03.06 16:14
답변 쓰기
이 입력폼은 마크다운 문법을 지원합니다. 마크다운 가이드 를 참고하세요.