Java 불변 클래스 메커니즘 분석

가변 클래스 없음(Immutable Class): 가변 클래스란 이 클래스의 인스턴스가 작성된 후 구성원 변수 값을 변경할 수 없는 것을 말합니다.예를 들어 JDK 내부에 자체적으로 가지고 있는 많은 불변류는 인터거, 롱, 스트링 등이다.
가변 클래스(Mutable Class): 가변 클래스에 비해 가변 클래스는 인스턴스를 작성한 후 멤버 변수 값을 변경할 수 있으며 개발 중에 생성된 대부분의 클래스는 가변 클래스에 속합니다.
불변류의 특성은 JAVA에 어떤 장점을 가져다 줍니까?
1) 스레드 안전: 불변 대상은 스레드 안전으로 스레드 간에 서로 공유할 수 있으며 특수한 메커니즘을 이용하여 동기화 문제를 보장할 필요가 없다. 왜냐하면 대상의 값은 바꿀 수 없기 때문이다.일부 잠금 메커니즘 등 메모리 일치성을 확보하지 않아도 동기화 비용을 줄일 수 있기 때문에 병발 오류의 가능성을 낮출 수 있다.
2) 구성, 사용 및 테스트가 용이합니다.
불가변류의 설계 원칙
어떻게 Java에서 Immutable 클래스를 작성합니까?이러한 클래스를 작성하려면 다음과 같은 몇 가지 원칙을 따라야 한다.
1) immutable 대상의 상태는 창설된 후에 변경될 수 없으며, 그 어떠한 변경도 새로운 대상이 되어야 한다.
2) Immutable 클래스의 모든 구성원은 private final이어야 합니다.이런 방식을 통해 구성원의 변수를 바꿀 수 없음을 보증한다.그러나 이 정도만으로는 부족하다. 만약에 구성원 변수가 대상이라면 인용만 저장하고 외부에서 인용이 가리키는 값을 바꿀 수 있기 때문에 다섯 번째는 이 부족함을 보완한다
3) 대상은 반드시 정확하게 만들어져야 한다. 예를 들어 대상 인용은 대상 창설 과정에서 누설해서는 안 된다.4) 구성원 변수를 읽는 get 방법만 제공하고 구성원 변수를 바꾸는 set 방법은 제공하지 않으며 다른 인터페이스를 통해 구성원 변수의 값을 바꾸지 않고 변수의 특성을 파괴하지 않습니다.
5) 클래스는final의 것이어야 한다. 클래스가 계승되지 않도록 보증한다. 만약에 클래스가 계승될 수 있다면 클래스의 불가변성 메커니즘을 파괴할 수 있다. 계승류가 부류를 덮어쓰는 방법과 계승류가 구성원의 변수 값을 바꿀 수 있다면 부류가 부류의 형식으로 나타날 때 전류가 변할 수 있는지 보장할 수 없다.
6) 클래스에mutable 클래스 대상이 포함되어 있으면 클라이언트에게 돌아갈 때 그 대상의 깊은 복사본을 되돌려줍니다. 그 대상 자체가 아닙니다. (이 조항은 첫 번째 조항의 특례로 분류할 수 있습니다)
구조기가 전송한 대상을 구성원 변수에 직접 값을 부여할 경우, 전송된 대상에 대한 수정을 통해 내부 변수의 값을 변경할 수 있습니다.예:

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();  
  }  
}
String 클래스의 불변 구현
String 대상은 메모리가 생성된 후에 변경할 수 없습니다. 변경할 수 없는 대상의 생성은 일반적으로 상기 원칙을 만족시킵니다. String 코드가 어떻게 실현되는지 봅시다.

public final class String
  implements java.io.Serializable, Comparable<String>, CharSequence
{
  private final char value[]; /** The value is used for character storage. */
  /** 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;
  private int hash; // Default to 0
  ....
  public String(char value[]) {
     this.value = Arrays.copyOf(value, value.length); // deep copy 
   }
   public char[] toCharArray() {
    char result[] = new char[value.length];
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
  }
  ...
}
코드에서 보듯이 String류의 디자인은 위에서 정리한 변하지 않는 유형의 디자인 원칙에 부합되는 것을 관찰할 수 있다.String 객체는value를final로 설정하고 구성원 변수를 변경할 수 없도록 다양한 메커니즘을 통해 보장합니다.그러나 반사 메커니즘을 통해 그 값을 바꿀 수 있다.예:

String s = "Hello World"; // "Hello World",  s
System.out.println("s = " + s);   
// String value 
Field valueFieldOfString = String.class.getDeclaredField("value");
valueFieldOfString.setAccessible(true); // 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의 불변성은 주로 상량 탱크, 스레드 안전, 클래스 불러오는 수요를 만족시키기 위한 것이다.불가변류를 합리적으로 사용하면 매우 큰 이익을 가져올 수 있다.
위에서 말한 것은 편집자가 여러분께 소개한 자바 불변류 메커니즘에 대한 간단한 분석입니다. 여러분께 도움이 되었으면 합니다. 만약에 궁금한 점이 있으면 저에게 메시지를 남겨 주시면 편집자는 제때에 답장을 드리겠습니다!

좋은 웹페이지 즐겨찾기