불변이란 무엇을 의미합니까?


103

문자열이 불변이라면 그 의미는 .... (자바 스크립트를 가정하자)

var str = 'foo';

alert(str.substr(1)); // oo

alert(str); // foo

문자열에 대해 메서드를 호출 할 때 수정 된 문자열을 반환하지만 초기 문자열은 변경하지 않는다는 의미입니까?

문자열이 변경 가능하다면 두 번째 alert()도 반환 oo될까요?

답변:


104

개체를 인스턴스화하면 속성을 변경할 수 없음을 의미합니다. 첫 번째 경고에서 foo를 변경하지 않습니다. 새 문자열을 만들고 있습니다. 이것이 두 번째 경고에서 oo 대신 "foo"를 표시하는 이유입니다.

문자열에 대해 메서드를 호출 할 때 수정 된 문자열을 반환하지만 초기 문자열은 변경하지 않는다는 의미입니까?

예. 문자열이 생성되면 아무것도 변경할 수 없습니다. 이제 이것이 str변수에 새 문자열 객체를 할당 할 수 없다는 의미는 아닙니다 . str이 참조하는 현재 객체를 변경할 수 없습니다.

문자열이 변경 가능하다면 두 번째 alert ()도 oo를 반환한다는 의미입니까?

기술적으로는 아니요, 하위 문자열 메서드가 새 문자열을 반환하기 때문입니다. 객체를 변경 가능하게 만들어도 메서드가 변경되지 않습니다. 변경 가능하게 만드는 것은 기술적으로 하위 문자열이 새 문자열을 만드는 대신 원래 문자열을 변경하도록 만들 수 있음을 의미합니다.


수정 및 할당 된 동일한 문자열은 문자열을 업데이트합니다. var str = 'foo'; str = str.substr (1)); // oo alert (str); // oo
Ashwin G

아래 코드는 어떻습니까? 이제 문자열 값이 변경되었습니다. var name = "Santosh"; console.log (name.substr (0,2)); var name = "kumar"console.log (name); 어떻게 그 여전히 불변
산토

97

낮은 수준에서 불변성은 문자열이 저장된 메모리가 수정되지 않음을 의미합니다. 문자열을 생성 "foo"하면 값을 저장하기 위해 일부 메모리가 할당됩니다 "foo". 이 메모리는 변경되지 않습니다. 예를 들어를 사용하여 문자열을 수정하면 substr(1)새 문자열이 생성되고을 저장할 메모리의 다른 부분이 할당됩니다 "oo". 이제 메모리에 두 개의 문자열이 "foo"있고 "oo". "foo"더 이상 사용하지 않더라도 쓰레기가 수거 될 때까지 계속 붙어 있습니다.

문자열 연산이 상대적으로 비용이 많이 드는 이유 중 하나입니다.


1
숫자도 변경할 수 없습니다.
RN Kushwaha

3
2015 년부터 안녕하세요 !! "낮은 수준에서 불변성은 문자열이 저장된 메모리가 수정되지 않음을 의미합니다."--- 이것은 너무 제한적이며 제대로 들리지 않습니다. 불변성은 단지 사용자 영역에 관한 것이며, 언어 사양 불변이 유지되는 즉시 메모리 할당자가 좋아하는대로 가상 메모리가 변경 될 수 있습니다.
zerkms

2
이 대답은 합격 된 대답보다 더 논리적입니다.
Ejaz 카림

하지만 나는 var str = 'foo'처럼 할 수 있습니다; str = 'bar'를 통해 수정할 수 있습니다. str 값이 이렇게 수정 되었습니까?
Hacker

@Hacker Nope. 메모리의 새 위치를 가리키는 변수에 새 문자열을 할당했습니다.
deceze

13

불변이란 변경하거나 수정할 수 없음을 의미합니다.

따라서 문자열에 값을 할당 할 때이 값은 대체되는 것이 아니라 처음부터 만들어집니다. 따라서 동일한 문자열에 새 값이 할당 될 때마다 복사본이 생성됩니다. 따라서 실제로는 원래 값을 변경하지 않습니다.


9

JavaScript에 대해 확신 할 수는 없지만 Java에서 문자열은 "문자열 상수 풀"을 사용하여 불변성에 대한 추가 단계를 수행합니다. 문자열은 문자열 리터럴 ( "foo") 또는 String클래스 생성자를 사용하여 생성 할 수 있습니다 . 문자열 리터럴로 구성된 문자열은 문자열 상수 풀의 일부이며 동일한 문자열 리터럴은 항상 풀의 동일한 메모리 주소가됩니다.

예:

    String lit1 = "foo";
    String lit2 = "foo";
    String cons = new String("foo");

    System.out.println(lit1 == lit2);      // true
    System.out.println(lit1 == cons);      // false

    System.out.println(lit1.equals(cons)); // true

위의 경우 lit1및 둘 다 lit2동일한 문자열 리터럴을 사용하여 구성되므로 동일한 메모리 주소를 가리키고 있습니다. lit1 == lit2결과 true는 정확히 동일한 객체이기 때문입니다.

그러나 cons클래스 생성자를 사용하여 생성됩니다. 파라미터가 동일한 문자열 상수이지만, 새로운 메모리의 생성자 할당은 cons의미가 cons같은 오브젝트가 아닌 lit1lit2동일한 데이터를 포함 불구.

물론 세 문자열은 모두 동일한 문자 데이터를 포함하므로 equals메서드를 사용하면 true가 반환됩니다.

(물론 두 가지 유형의 문자열 구성은 변경할 수 없습니다.)


3

불변은 값을 변경할 수 없음을 의미합니다. 일단 생성 된 문자열 객체는 불변으로 수정할 수 없습니다. 문자열의 하위 문자열을 요청하면 요청 된 부분이있는 새 문자열이 생성됩니다.

대신 문자열을 조작하는 동안 StringBuffer를 사용하면 StringBuffer가 문자열을 문자 배열의 용량과 배열의 길이를 보유하는 변수가있는 문자 배열에 저장하므로 작업이 더 효율적입니다 (문자 배열 형식의 문자열).


3

변경 가능성의 교과서 정의는 책임이 있거나 변경 또는 변경 될 수 있습니다. 프로그래밍에서 우리는 시간이 지남에 따라 상태가 변경 될 수있는 객체를 의미하는 단어를 사용합니다. 변경 불가능한 값은 정반대입니다. 생성 된 후에는 변경할 수 없습니다.

이것이 이상하게 느껴진다면, 우리가 항상 사용하는 많은 값들은 사실상 불변이라는 것을 상기시켜 드리겠습니다.

var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);

두 번째 줄이 문장의 문자열을 변경하지 않는다는 사실에 아무도 놀라지 않을 것이라고 생각합니다. 사실, 문자열 메서드는 작동하는 문자열을 변경하지 않으며 모두 새 문자열을 반환합니다. 그 이유는 문자열은 불변이기 때문입니다. 문자열은 변경할 수 없으며 새로운 문자열 만 만들 수 있습니다.

문자열은 JavaScript에 내장 된 유일한 불변 값이 아닙니다. 숫자도 변경할 수 없습니다. 표현 2 + 3을 평가하면 숫자 2의 의미가 바뀌는 환경을 상상할 수 있습니까? 어리석게 들리지만 우리는 항상 객체와 배열로 이것을합니다.


2

문자열에서 스택까지 ... Eric Lippert의 블로그 에서 가져온 이해하기 쉬운 예제 :

C # 3.0에서 A *를 사용한 경로 찾기, 2 부 ...

System.Collections.Generic.Stack과 같은 변경 가능한 스택은 분명히 적합하지 않습니다. 우리는 기존 경로를 가져 와서 마지막 요소의 모든 이웃에 대해 새 경로를 만들 수 있기를 원하지만 새 노드를 표준 스택에 푸시하면 스택이 수정됩니다. 스택을 푸시하기 전에 복사본을 만들어야하는데, 이는 모든 내용을 불필요하게 복제 할 것이기 때문입니다.

불변 스택에는이 문제가 없습니다. 변경 불가능한 스택에 밀어 넣으면 기존 스택을 꼬리로 연결하는 새로운 스택이 생성됩니다. 스택은 불변이기 때문에 다른 코드가 따라 와서 꼬리 내용을 엉망으로 만들 위험이 없습니다. 이전 스택을 마음껏 사용할 수 있습니다.

불변성을 이해하려면 다음으로 시작하는 Eric의 게시물을 읽어보십시오.

C #의 불변성 1 부 : 불변성의 종류


이 인용문에는 스택 데이터 구조 (실제로 테일 공유가있는 다중 스택)가 전체적으로 가변 구조라는 이상한 주장이 포함되어 있습니다. 모든 푸시 또는 팝이 구조를 변경합니다. 개별 항목 만 변경할 수 없습니다. 원칙적으로 동일한 구조를 가질 수 있지만 변경 가능한 요소가 있습니다. 이것은 실행 취소 가능한 union-find IIRC의 일부 변형에서 발생합니다. 불변성은 큰 장점이 있지만, 데이터 구조의 일부 또는 전체를 최적화로 공유하는 것은 변경 가능 항목으로 완벽하게 가능합니다. 다른 참조에 대한 명백한 불변성을 원하는 경우에도 필요에 따라 언제든지 쓰기시 복사 할 수 있습니다.
Steve314

0

이 개념을 이해하는 한 가지 방법은 자바 스크립트가 모든 객체를 처리하는 방법을 참조하는 것입니다. 즉, 모든 개체는 인스턴스화 후 변경 가능 합니다. 즉, 새 메서드와 속성을 사용하여 개체를 추가 할 수 있습니다. 개체를 변경 불가능하게하려면 인스턴스화 된 후에 개체를 변경할 수 없기 때문에 이는 중요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.