JAVA 불가 변류기 (immutable) 메커니즘 과 String 의 불가 변성
5984 단어 자바
가 변 하지 않 는 클래스: 가 변 하지 않 는 클래스 란 이러한 인 스 턴 스 가 생 성 되면 구성원 변수 값 을 바 꿀 수 없다 는 것 을 말 합 니 다.예 를 들 어 JDK 내부 에 자체 적 으로 가지 고 있 는 많은 가 변 류: Interger, Long, String 등 이다.가 변 클래스: 가 변 클래스 에 비해 가 변 클래스 가 인 스 턴 스 를 만 든 후에 구성원 변 수 를 바 꿀 수 있 습 니 다. 개발 에서 만 든 대부분의 클래스 는 가 변 클래스 에 속 합 니 다.
2. 불가 변류의 장점
가 변 류 와 가 변 류 의 차 이 를 말 하면 우 리 는 왜 가 변 류 가 있어 야 하 는 지 더 알 아야 한다.이런 특성 이 JAVA 에 게 어떤 이점 을 가 져 다 줍 니까?
3. 불가 변 류 의 디자인 방법
디자인 불가 변 류 에 대해 개인 은 다음 과 같은 원칙 을 요약 한다.
1. 클래스 에 final 장식 부 호 를 추가 하여 클래스 가 계승 되 지 않도록 보증 합 니 다.만약 에 클래스 가 계승 되면 클래스 의 불가 변성 체 제 를 파괴 할 수 있 습 니 다. 계승 류 가 부모 류 를 덮 는 방법 과 계승 류 가 구성원 변수 값 을 바 꿀 수 있다 면 하위 클래스 가 부모 류 의 형식 으로 나타 날 때 현재 클래스 가 변 할 수 있 는 지 여 부 를 보장 할 수 없습니다.
2. 모든 구성원 변 수 는 개인 적 이 어야 하 며 final 수식 을 추가 하여 이러한 방식 으로 구성원 변 수 를 바 꿀 수 없 도록 확보한다.그러나 이 정도 만 으로 는 부족 하 다. 대상 구성원 변수 라면 외부 에서 값 을 바 꿀 수 있 기 때문이다.그래서 네 번 째 는 이 부족 함 을 보완 한다.
3. 구성원 변 수 를 바 꾸 는 방법 을 제공 하지 않 습 니 다. setter 는 다른 인 터 페 이 스 를 통 해 구성원 변수의 값 을 바 꾸 지 않 고 가 변 적 인 특성 을 파괴 하지 않도록 합 니 다.
4. 구조 기 를 통 해 모든 구성원 을 초기 화하 고 딥 카피 (deep copy)
만약 에 구조 기 가 들 어 오 는 대상 이 구성원 변수 에 직접 값 을 부여 하면 들 어 오 는 대상 에 대한 수정 을 통 해 내부 변수의 값 을 바 꿀 수 있다.예 를 들 면:
public final class ImmutableDemo {
private final int[] myArray;
public ImmutableDemo(int[] array) {
this.myArray = array; // wrong
}
}
이 방식 은 불변성 을 보장 할 수 없습니다. my Array 와 array 는 같은 메모리 주 소 를 가리 키 고 있 습 니 다. 사용 자 는 ImmutableDemo 외 에 array 대상 의 값 을 수정 하여 my Array 내부 의 값 을 변경 할 수 있 습 니 다.내부 값 이 수정 되 지 않도록 깊이 copy 를 사용 하여 들 어 오 는 값 을 저장 할 수 있 습 니 다.올 바른 방법:
public final class MyImmutableDemo {
private final int[] myArray;
public MyImmutableDemo(int[] array) {
this.myArray = array.clone();
}
}
5. getter 방법 에서 대상 자 체 를 직접 되 돌려 주지 않 고 복제 대상 을 되 돌려 주 는 복사 방법 도 대상 의 유출 을 방지 하고 getter 를 통 해 내부 가 변 멤버 대상 을 얻 은 후에 구성원 변 수 를 직접 조작 하여 구성원 변 수 를 변화 시 키 는 것 을 방지 합 니 다.
4. String 대상 의 불변성
string 대상 은 메모리 생 성 후 변경 할 수 없습니다. 변경 할 수 없 는 대상 의 생 성 은 일반적으로 상기 5 가지 원칙 을 만족 시 킵 니 다. String 코드 가 어떻게 실현 되 는 지 봅 시다.
public final class String
implements java.io.Serializable, Comparable, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
....
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length); // deep copy
}
...
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
...
}
상기 코드 에서 보 듯 이 다음 과 같은 디자인 디 테 일 을 관찰 할 수 있 습 니 다.
5. String 대상 의 불가 변성 장단 점
이전 절 에서 분석 하면 String 데 이 터 는 가 변 류 가 아 닙 니 다. 그러면 이러한 특성 을 설정 하면 어떤 장점 이 있 습 니까?나 는 다음 과 같은 몇 가지 로 요약 한다.
1. 문자열 상수 탱크 의 필요. 문자열 상수 탱크 는 상수 탱크 에 일부 문자 상 수 를 두 고 반복 적 으로 사용 할 수 있 으 며 매번 같은 대상 을 다시 만 들 거나 저장 공간 을 절약 하지 않도록 합 니 다.그러나 문자열 이 가 변 적 이면 같은 내용 의 String 은 상수 탱크 의 같은 메모리 공간 을 가리 키 며, 어떤 변수 가 이 메모리 의 값 을 바 꾸 었 을 때 다른 옮 겨 다 니 는 값 도 변 경 됩 니 다.그래서 상수 탱크 디자인 의 취지 에 맞지 않 습 니 다.
2. 라인 안전 고려.같은 문자열 인 스 턴 스 는 여러 스 레 드 에서 공유 할 수 있 습 니 다.이렇게 하면 스 레 드 안전 문제 로 동기 화 를 사용 하지 않 아 도 된다.문자열 자체 가 라인 이 안전 합 니 다.
3. 클래스 로 더 는 문자열 을 사용 해 야 합 니 다. 정확 한 클래스 를 불 러 올 수 있 도록 보안 을 제공 합 니 다.예 를 들 어 자바. sql. connection 류 를 불 러 오고 싶 은 데 이 값 이 my hacked. Connection 으로 바 뀌 면 데이터 베 이 스 를 알 수 없 는 파 괴 를 초래 할 수 있 습 니 다.
4. hash 맵 과 캐 시 를 지원 합 니 다.문자열 은 가 변 적 이지 않 기 때문에 만 들 때 hashcode 가 캐 시 되 어 다시 계산 할 필요 가 없습니다.이 때문에 문자열 은 Map 의 키 로 적합 하고 문자열 의 처리 속 도 는 다른 키 대상 보다 빠르다.이것 이 바로 HashMap 의 키 입 니 다. 문자열 을 자주 사용 합 니 다.
단점:
6. String 대상 의 진짜 불가 변 여부
String 대상 은 value 를 final 로 설정 하고 여러 메커니즘 을 통 해 구성원 변 수 를 변경 할 수 없 도록 합 니 다.하지만 반사 메커니즘 의 수단 을 통 해 그 값 을 바 꿀 수 있다.예 를 들 면:
// "Hello World", s
String s = "Hello World";
System.out.println("s = " + s); //Hello World
// String value
Field valueFieldOfString = String.class.getDeclaredField("value");
// value
valueFieldOfString.setAccessible(true);
// s value
char[] value = (char[]) valueFieldOfString.get(s);
// value 5
value[5] = '_';
System.out.println("s = " + s); //Hello_World
인쇄 결과:
s = Hello World
s = Hello_World
String 의 값 이 변경 되 었 습 니 다.반 사 를 통 해 이른바 '불가 변' 대상 을 수정 할 수 있다 는 것 이다.
총결산
가 변 하지 않 는 클래스 는 인 스 턴 스 생 성 후 구성원 이 옮 겨 다 니 는 값 을 바 꿀 수 없습니다.이러한 특성 으로 인해 불 가 변 류 는 스 레 드 안전 기능 을 제공 하지만 대상 이 만 든 비용 도 가 져 왔 습 니 다. 속성 을 변경 할 때마다 새로운 대상 을 다시 만 듭 니 다.JDK 내부 에서 도 Integer, Double, String 등 가 변 적 이지 않 은 종 류 를 많이 제공 했다.String 의 가 변 적 이지 않 은 특성 은 주로 상수 탱크, 스 레 드 안전, 클래스 로드 의 수 요 를 만족 시 키 기 위해 서 입 니 다.불가 변 류 를 합 리 적 으로 사용 하면 매우 큰 이익 을 가 져 올 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.