openlang

읽기 전용 List<Int>는 스냅샷인가요?

List<Int>는 읽기 전용 뷰예요. 스냅숏이 아니에요. 그 참조로 어떤 연산을 호출할 수 있는지 알려 줄 뿐, 뒤에 있는 컬렉션이 그대로 남는다고 약속하지는 않아요.

val owned = mutableListOf(2, 4)를 예로 들어 볼게요. 호출자가 owned를 List<Int>를 받는 함수에 넘기고, 나중에 6을 추가해요. 함수가 같은 객체를 쥐고 있었다면 이제 6도 보여요. val이 고정한 건 owned가 가진 참조예요. 내용은 처음부터 고정된 적이 없어요.

결국 함수가 무엇을 필요로 하느냐에 달렸어요. 넘겨받은 순간의 값이 필요하다면 정해진 지점에서 복사하고, 그 복사본이 나중에 바뀌지 않게 막아야 해요. 이 경계는 시그니처나 문서에 명시해 두겠어요. 호출자의 현재 리스트를 읽는 게 목적이라면 공유 객체를 그대로 들고 있어도 괜찮고, 복사해 봐야 얻는 게 없어요.

이어지는 대화 2

서로의 근거를 따라
  1. 고유 링크

    API 입구에서의 방어적 복사는 보기보다 쌉니다. Collections.unmodifiableList(list)는 뷰일 뿐이라 호출한 쪽이 나중에 add 하면 그대로 비쳐 보입니다. List.copyOf(list)는 수정할 수 없는 스냅숏이고, 이미 그런 의미로 수정 불가능한 목록, 즉 List.of나 앞서 만든 copyOf 결과를 넘기면 대개 복사하지 않고 같은 객체를 돌려줍니다. 이것이 Java의 답이고, 이 세부 사항 덕분에 복사를 기본으로 해도 될 만큼 싸집니다.

  2. 고유 링크

    사람들은 readonly number[]를 늘 스냅숏으로 읽는데, 그렇지 않아요. 평범한 number[]를 거기에 대입할 수 있어서 호출한 쪽은 변경 가능한 핸들을 그대로 갖고 있어요. "복사본"이라는 말은 타입보다 맞는 줄에 넣은 slice()가 더 잘해요.

같은 질문의 다른 갈래

  1. 판별 유니온 전에 JSON 검증하기

    타입 단언은 파서가 아니에요. 외부 응답은 바이트로 시작하고, 누군가 확인하기 전까지는 그게 어떤 변형인지 알려 주는 게 하나도 없어요. 텍스트 디코딩과 JSON 파싱이 먼저 오고, 둘 다 각자 실패할 수 있어요. 파서에서…