JAVA 불가변 클래스(immutable) 메커니즘과 String의 불가변성(추천)

5388 단어 javastringimmutable
1. 불가변 클래스 소개
불변 클래스: 불변 클래스란 이 클래스의 실례가 생성된 후에 구성원 변수 값을 바꿀 수 없다는 것을 가리킨다.예를 들어 JDK 내부에 자체적으로 가지고 있는 많은 불변류는 인터거, 롱, 스트링 등이다.
가변 클래스: 가변 클래스에 비해 가변 클래스는 인스턴스를 작성한 후 멤버 변수 값을 변경할 수 있으며 개발 중에 생성된 대부분의 클래스는 가변 클래스에 속합니다.
2. 불가변류의 장점
가변류와 가변류의 차이를 말하자면, 우리는 왜 가변류가 있는지 더욱 이해해야 한다.이러한 특성은 JAVA에게 어떤 이점을 가져다 줍니까?
1. 스레드 보안
불변 대상은 스레드가 안전하고 스레드 간에 서로 공유할 수 있으며 특수한 메커니즘을 이용하여 동기화 문제를 보장할 필요가 없다. 왜냐하면 대상의 값이 바꿀 수 없기 때문이다.일부 잠금 메커니즘 등 메모리 일치성을 확보하지 않아도 동기화 비용을 줄일 수 있기 때문에 병발 오류의 가능성을 낮출 수 있다.
2. 구성, 사용 및 테스트가 용이함
삼....
3. 불변류의 디자인 방법
디자인 불변 클래스에 대해 개인은 다음과 같은 원칙을 요약한다.
1. 클래스는final 수식자를 추가하여 클래스가 계승되지 않도록 보증합니다.
만약에 클래스가 계승될 수 있다면 클래스의 불가변성 메커니즘을 파괴할 수 있다. 계승 클래스가 부류를 덮어쓰는 방법과 계승 클래스가 구성원의 변수 값을 바꿀 수 있다면 일단 부류가 부류의 형식으로 나타날 때 현재 클래스가 변할 수 있는지 보장할 수 없다.
2. 모든 구성원 변수는 반드시 사유화되어야 하며final 수식을 덧붙여야 한다
이런 방식을 통해 구성원의 변수를 바꿀 수 없음을 보증한다.그러나 이 정도로는 충분하지 않다. 대상 구성원 변수의 경우 외부에서 값을 바꿀 수 있기 때문이다.그래서 4시에 이 부족함을 보완한다.
3. 구성원 변수를 바꾸는 방법은 제공하지 않습니다. setter를 포함합니다.
다른 인터페이스를 통해 구성원 변수의 값을 바꾸는 것을 피하고 불변의 특성을 파괴합니다.
4. 구조기를 통해 모든 구성원을 초기화하고 딥 복사(deep copy)
만약 구조기가 전송한 대상이 구성원 변수에 직접 값을 부여한다면, 전송된 대상에 대한 수정을 통해 내부 변수의 값을 바꿀 수 있다.예:

public final class ImmutableDemo { 
private final int[] myArray; 
public ImmutableDemo(int[] array) { 
this.myArray = array; // wrong 
} 
}
이런 방식은 불가변성을 보장할 수 없다. myArray와array는 같은 메모리 주소를 가리키며, 사용자는ImmutableDemo 외에array 대상의 값을 수정하여 myArray 내부의 값을 변경할 수 있다.
내부 값이 수정되지 않도록 깊이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<String>, 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;
}
...
} 
위의 코드와 같이 다음 설계 세부 사항을 볼 수 있습니다.
1. String 클래스는 final로 수식되며 상속할 수 없습니다.
2.string 내부의 모든 구성원을 개인 변수로 설정
3.value가 없는 setter
4. value와 offset을 final로 설정합니다.
5. 가변수 그룹value[]를 전송할 때,value[]를 내부 변수에 직접 복사하지 않고copy를 합니다.
6.value를 가져올 때 대상 인용을 직접 되돌려주는 것이 아니라 대상을 되돌려주는copy입니다.
이것은 모두 위에서 정리한 변하지 않는 유형의 특성에 부합되고 String 유형이 변하지 않는 유형이라는 것을 보장한다.
5. String 객체의 변경할 수 없는 장단점
이전 절에서 분석한 바에 의하면 String 데이터는 변할 수 없는 종류가 있는데 이런 특성을 설정하면 어떤 장점이 있습니까?다음과 같이 요약합니다.
1. 문자열 상수 탱크의 필요.
문자열 상수 풀은 일부 문자 상수를 상수 풀에 놓고 반복해서 사용할 수 있으며, 매번 같은 대상을 다시 만들지 않고 저장 공간을 절약할 수 있다.그러나 문자열이 변할 수 있다면, 이 때 같은 내용의 String은 상수 탱크의 같은 메모리 공간을 가리키고, 어떤 변수가 이 메모리의 값을 바꾸면 다른 반복되는 값도 바뀐다.그래서 상량지 설계의 취지에 맞지 않는다.
2. 라인 안전 고려.
같은 문자열 실례는 여러 라인에 공유될 수 있습니다.이렇게 하면 스레드 안전 문제로 인해 동기화를 사용할 필요가 없다.문자열 자체가 안전하다.
3. 클래스 마운트는 문자열을 사용해야 하며, 정확한 클래스가 마운트될 수 있도록 안전성을 제공합니다.예를 들어 자바를 불러오고 싶어요.sql.연결 클래스, 이 값은 myhacked로 변경되었습니다.Connection, 그러면 데이터베이스에 알 수 없는 파괴를 초래할 수 있습니다.
4. hash 맵과 캐시를 지원합니다.
문자열은 변경할 수 없기 때문에 만들 때hashcode는 캐시되어 다시 계산할 필요가 없습니다.이로써 문자열은 맵의 키로 적합하고 문자열의 처리 속도가 다른 키 대상보다 빠르다.이것이 바로 HashMap의 키들이 종종 문자열을 사용하는 것이다.
단점:
1. String 객체 값 변경에 대한 요구가 있으면 대량의 String 객체가 생성됩니다.
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의 불변성은 주로 상량 탱크, 스레드 안전, 클래스 불러오는 수요를 만족시키기 위한 것이다.불가변류를 합리적으로 사용하면 매우 큰 이익을 가져올 수 있다.
위에서 말한 것은 편집자가 여러분께 소개한 JAVA 불변류(immutable) 메커니즘과 String의 불가변성(추천)입니다. 여러분께 도움이 되었으면 합니다. 궁금한 점이 있으면 저에게 메시지를 남겨 주십시오. 편집자는 제때에 답장을 드리겠습니다.여기에서도 저희 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기